-
Notifications
You must be signed in to change notification settings - Fork 0
/
marshal.go
72 lines (60 loc) · 1.6 KB
/
marshal.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
package packer
func Marshal(data []KeyValStore) []byte {
var keySize, valSize, mapLen, oneKeyValueSize, mapLenSize, formatSize, headerSize, maxVal, currentPosition, format uint32
keySize, valSize, maxVal = calcSizeAndMaxVal(data)
format = keySize<<4 | valSize
formatSize = 1
mapLen = uint32(len(data))
mapLenSize = 4
headerSize = formatSize + mapLenSize + valSize
oneKeyValueSize = keySize + valSize
resultBytes := make([]byte, headerSize+(mapLen*oneKeyValueSize))
resultBytes[currentPosition] = byte(format)
currentPosition++
putUint(resultBytes, mapLen, currentPosition)
currentPosition += mapLenSize
putUint(resultBytes, maxVal, currentPosition)
currentPosition += valSize
for _, item := range data {
putUint(resultBytes, item.Key, currentPosition)
currentPosition += keySize
putUint(resultBytes, item.Val, currentPosition)
currentPosition += valSize
}
return resultBytes
}
func calcSizeAndMaxVal(data []KeyValStore) (keySize, valSize, maxCnt uint32) {
for _, item := range data {
tSize := GetRequiredNumberOfBytesUint32(item.Key)
if keySize < tSize {
keySize = tSize
}
tSize = GetRequiredNumberOfBytesUint32(item.Val)
if valSize < tSize {
valSize = tSize
}
if maxCnt < item.Val {
maxCnt = item.Val
}
}
return
}
func GetRequiredNumberOfBytesUint32(num uint32) uint32 {
switch true {
case num <= 1<<8-1: // 255
return 1
case num <= 1<<16-1: // 65535
return 2
case num <= 1<<24-1: // 16777215
return 3
default: // 4294967295
return 4
}
}
func putUint(buf []byte, num, start_pos uint32) {
for num > 0 {
buf[start_pos] = byte(num)
num >>= 8
start_pos++
}
}