@@ -2,22 +2,49 @@ package varint
2
2
3
3
import "github.com/golang-infrastructure/go-gtypes"
4
4
5
- // ------------------------------------------------ ---------------------------------------------------------------------
5
+ // 这个文件中存放的是比较靠底层的方法实现,上层的API都是对这些底层方法的进一步封装
6
+ // 约定:
7
+ // 1. varint编码的字节数组约定以字节的最高位的值来表示某个无符号整数对应的多个字节是否结束,
8
+ // 如果传入的要解码的字节数组没有正确设置结束标志位的话,会一直读取到字节数组结束位置都认为是当前数字的值的一部分,这可能会发生溢出
9
+
10
+ // ---------------------------------------------------------------------------------------------------------------------
11
+
12
+ const (
13
+
14
+ // VarIntEndByteHighestBitValue 对varint字节数组而言,如果某个字节的最高位的值是0表示这是当前数字variant编码字节数组的最后一个字节
15
+ VarIntEndByteHighestBitValue = 0x0
16
+
17
+ // VarIntNotEndByteHighestBitValue 对varint字节数组而言,如果某个字节的最高位的值是1表示这不是当前数字varint编码字节数组的最后一个字节,后面至少还有一个字节
18
+ VarIntNotEndByteHighestBitValue = 0x1
19
+ )
20
+
21
+ // ByteHighestBit 获取byte的最高位
22
+ const ByteHighestBit = 0x80
23
+
24
+ // 0对应的varint编码
25
+ var ZeroVarIntBytes = []byte {VarIntNotEndByteHighestBitValue << 7 }
26
+
27
+ // ---------------------------------------------------------------------------------------------------------------------
6
28
7
29
// Encode 对无符号类型进行编码,注意,如果被编码的数字位数较小可能会越编码越大
8
30
func Encode [T gtypes.Unsigned ](value T ) []byte {
9
31
bytes := make ([]byte , 0 )
32
+
33
+ // 只要不是读取到了最后一个字节就一直读取
10
34
for value > 127 {
11
- bit := (value & 0x7F ) | 0x80
35
+ bit := (value & 0x7F ) | ( VarIntNotEndByteHighestBitValue << 7 )
12
36
value >>= 7
13
37
bytes = append (bytes , uint8 (bit ))
14
38
}
15
- if value > 0 {
16
- bytes = append (bytes , uint8 (value & 0x7F ))
17
- }
39
+
40
+ // 设置结束标志位,结束标志位是强制必须设置的
41
+ v := uint8 (value & 0x7F ) | (VarIntEndByteHighestBitValue << 7 )
42
+ bytes = append (bytes , v )
43
+
18
44
return bytes
19
45
}
20
46
47
+ // EncodeSlice 对无符号切片编码,切片中的无符号数字会被挨个存储在返回的字节切片中
21
48
func EncodeSlice [T gtypes.Unsigned ](valueSlice []T ) []byte {
22
49
slice := make ([]byte , 0 )
23
50
for _ , value := range valueSlice {
@@ -26,7 +53,7 @@ func EncodeSlice[T gtypes.Unsigned](valueSlice []T) []byte {
26
53
return slice
27
54
}
28
55
29
- // ------------------------------------------------ ---------------------------------------------------------------------
56
+ // ---------------------------------------------------------------------------------------------------------------------
30
57
31
58
// Decode 对varint编码的无符号整数进行解码,一次解码一个
32
59
func Decode [T gtypes.Unsigned ](bytes []byte ) T {
@@ -36,25 +63,33 @@ func Decode[T gtypes.Unsigned](bytes []byte) T {
36
63
r = r | (T (b & 0x7F ) << weight )
37
64
weight += 7
38
65
// 判断是否是最后一个字节,如果是最后一个字节说明当前这个数字读取完毕了
39
- if b & 0x80 == 0 {
66
+ if b & ByteHighestBit == VarIntEndByteHighestBitValue {
40
67
break
41
68
}
42
69
}
43
70
return r
44
71
}
45
72
46
- // DecodeSlice 解码varint编码的一整个个无符号切片,即一次解码多个
73
+ // DecodeSlice 当多个无符号整数放在同一个字节切片中时,可以调用这个方法解码
47
74
func DecodeSlice [T gtypes.Unsigned ](bytes []byte ) []T {
48
75
slice := make ([]T , 0 )
49
76
lastIndex := 0
50
77
for index , b := range bytes {
51
- if b & 0x80 == 0 {
78
+ // 当读取到当前无符号整数的最后一个字节的时候,截取当前无符号整数的全部字节传进去解码
79
+ if b & ByteHighestBit == VarIntEndByteHighestBitValue {
52
80
value := Decode [T ](bytes [lastIndex : index + 1 ])
53
81
slice = append (slice , value )
54
82
lastIndex = index + 1
55
83
}
56
84
}
85
+
86
+ // 说明有未读取处理完的内容,将剩下的内容一股脑儿的当做一个数字解码
87
+ if lastIndex < len (bytes ) {
88
+ value := Decode [T ](bytes [lastIndex :len (bytes )])
89
+ slice = append (slice , value )
90
+ }
91
+
57
92
return slice
58
93
}
59
94
60
- // ------------------------------------------------ ---------------------------------------------------------------------
95
+ // ---------------------------------------------------------------------------------------------------------------------
0 commit comments