forked from smhanov/zwibserve
-
Notifications
You must be signed in to change notification settings - Fork 0
/
encoder.go
176 lines (151 loc) · 2.96 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
package zwibserve
import (
"errors"
"reflect"
)
type initMessage struct {
MessageType uint8
More uint8
ProtocolVersion uint16
MaxMessageSize uint32
CreationMode uint8
Offset uint64
DocIDLength uint8
DocID string
Data []byte
}
type appendMessage struct {
MessageType uint8
More uint8
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
}
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 {
v := reflect.Indirect(reflect.ValueOf(s))
var value uint64
pos := 0
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
var size int
if kind == reflect.String {
size = int(value)
} else {
size = sizeof(kind)
}
if pos+size > len(m) {
return 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 {
value = readUint(m, pos, size)
field.SetUint(value)
}
pos += size
}
return 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
if kind == reflect.String {
m = append(m, []byte(field.String())...)
} else if name == "Data" {
m = append(m, field.Bytes()...)
} else if kind == reflect.Slice {
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
}