/
bsonencoder.go
75 lines (68 loc) · 1.6 KB
/
bsonencoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package gonami
import (
"reflect"
"strings"
"gopkg.in/mgo.v2/bson"
)
//a bit hacked together, but seems to be better than the default
//gobencoder
type BsonEncoder struct{}
func (b BsonEncoder) Encode(msg *Packet) ([]byte, error) {
data, err := bson.Marshal(msg)
if err != nil {
return nil, err
}
return data, nil
}
func (b BsonEncoder) Decode(data []byte, numBytes int) (*Packet, error) {
msg := Packet{}
err := bson.Unmarshal(data, &msg)
if err != nil {
return nil, err
}
switch msg.Type {
case GET_FILE:
if payload, ok := msg.Payload.(bson.M); ok {
c := Config{}
fillStruct(payload, &c)
msg.Payload = c
}
case DATA:
if payload, ok := msg.Payload.(bson.M); ok {
b := Block{}
fillStruct(payload, &b)
msg.Payload = b
}
case RETRANSMIT:
if payload, ok := msg.Payload.(bson.M); ok {
b := Retransmit{}
fillStruct(payload, &b)
pBlockNums := payload["blocknums"].([]interface{})
blockNums := make([]int, len(pBlockNums))
for i, block := range pBlockNums {
blockNums[i] = block.(int)
}
b.BlockNums = blockNums
msg.Payload = b
}
}
return &msg, nil
}
func fillStruct(data map[string]interface{}, result interface{}) {
t := reflect.ValueOf(result).Elem()
typeOfT := t.Type()
for i := 0; i < t.NumField(); i++ {
fieldName := typeOfT.Field(i).Name
v := strings.ToLower(fieldName)
if mVal, ok := data[v]; ok {
sVal := t.FieldByName(fieldName)
if fieldName == "Type" {
sVal.SetInt(int64(reflect.ValueOf(mVal).Interface().(int)))
} else if fieldName == "BlockNums" {
continue
} else {
sVal.Set(reflect.ValueOf(mVal))
}
}
}
}