-
Notifications
You must be signed in to change notification settings - Fork 6
/
encoder.go
245 lines (212 loc) · 4.83 KB
/
encoder.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
package zwibserve
import (
"errors"
"reflect"
)
const (
initMessageType = 0x01
appendV2MessageType = 0x02
setKeyMessageType = 0x03
broadcastMessageType = 0x04
appendMessageType = 0x05
errorMessageType = 0x80
ackNackMessageType = 0x81
keyInformationMessageType = 0x82
serverIdentificationMessageType = 0x84
swarmRegisterMessageType = 0x85
swarmDataMessageType = 0x86
continuationMessageType = 0xff
)
type initMessageV2 struct {
MessageType uint8
More uint8
ProtocolVersion uint16
MaxMessageSize uint32
CreationMode uint8
Offset uint64
DocIDLength uint8
DocID string
Data []byte
}
type initMessage struct {
MessageType uint8
More uint8
ProtocolVersion uint16
MaxMessageSize uint32
CreationMode uint8
Generation uint32
Offset uint64
DocIDLength uint32
DocID string
Data []byte
}
type appendMessageV2 struct {
MessageType uint8
More uint8
Offset uint64
Data []byte
}
type appendMessage struct {
MessageType uint8
More uint8
Generation uint32
Offset uint64
Data []byte
}
type setKeyMessage struct {
MessageType uint8
More uint8
RequestID uint16
Lifetime uint8
OldVersion uint32
NewVersion uint32
NameLength uint32
Name string
ValueLength uint32
Value string
}
type errorMessage struct {
MessageType uint8
More uint8
ErrorCode uint16
Description string
}
type ackNackMessage struct {
MessageType uint8
More uint8
Ack uint16
Offset uint64
}
type setKeyAckNackMessage struct {
MessageType uint8
More uint8
Ack uint16
RequestID uint16
}
type keyInformationMessage struct {
MessageType uint8
More uint8
Keys []keyInformation `repeat:"true"`
}
type keyInformation struct {
Version uint32
NameLength uint32
Name string
ValueLength uint32
Value string
}
type broadcastMessage struct {
MessageType uint8
More uint8
DataLength uint32
Data []byte
}
func sizeof(kind reflect.Kind) int {
var size int
switch kind {
case reflect.Uint8:
size = 1
case reflect.Uint16:
size = 2
case reflect.Uint32:
size = 4
case reflect.Uint64:
size = 8
}
return size
}
func decode(s interface{}, m []byte) error {
_, err := _decode(s, m, 0)
return err
}
func _decode(s interface{}, m []byte, pos int) (int, error) {
v := reflect.Indirect(reflect.ValueOf(s))
var value uint64
for i := 0; i < v.NumField(); i++ {
// Get the field tag value
field := v.Field(i)
kind := field.Kind()
name := v.Type().Field(i).Name
isBytes := kind == reflect.Slice && field.Type().Elem().Kind() == reflect.Uint8
var size int
if kind == reflect.String || isBytes && name != "Data" {
size = int(value)
} else {
size = sizeof(kind)
}
//log.Printf("Decode %s isbytes=%v size=%v", name, isBytes, size)
//log.Printf("At %v decode %v size is %v", pos, name, size)
if pos+size > len(m) {
return pos, errors.New("message too short")
}
if kind == reflect.String {
field.SetString(string(m[pos : pos+size]))
} else if name == "Data" {
field.SetBytes(m[pos:])
pos = len(m)
} else if kind == reflect.Slice {
if isBytes {
field.SetBytes(m[pos : pos+size])
} else {
// read the tag of the field
repeatToEnd := v.Type().Field(i).Tag.Get("repeat") == "true"
var err error
elemType := field.Type().Elem()
size = 0 // int(value) * int(elemType.Size())
for j := uint64(0); repeatToEnd && pos < len(m) || !repeatToEnd && j < value; j++ {
elemValue := reflect.New(elemType)
pos, err = _decode(elemValue.Interface(), m, pos)
if err != nil {
return pos, err
}
tmp := reflect.Append(field, reflect.Indirect(elemValue))
field.Set(tmp)
}
}
} else {
value = readUint(m, pos, size)
field.SetUint(value)
}
pos += size
}
return pos, nil
}
func encode(m []byte, s interface{}) []byte {
v := reflect.ValueOf(s)
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
kind := field.Kind()
//name := v.Type().Field(i).Name
//log.Printf("Encode %s=%+v", name, s)
if kind == reflect.String {
m = append(m, []byte(field.String())...)
} else if kind == reflect.Slice {
if field.Type().Elem().Kind() == reflect.Uint8 {
m = append(m, field.Bytes()...)
} else {
for j := 0; j < field.Len(); j++ {
m = encode(m, field.Index(j).Interface())
}
}
} else {
m = writeUint(m, field.Uint(), sizeof(kind))
}
}
return m
}
func readUint(m []byte, at, size int) uint64 {
var ret uint64
for size > 0 {
ret = ret*256 + uint64(m[at])
size--
at++
}
return ret
}
func writeUint(m []byte, v uint64, size int) []byte {
for size > 0 {
size--
m = append(m, byte(v>>(size*8)))
}
return m
}