Skip to content

Commit bf4d5fb

Browse files
committed
refactor encoding.go
1 parent 03b6c0d commit bf4d5fb

File tree

1 file changed

+45
-10
lines changed

1 file changed

+45
-10
lines changed

encoding.go

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,49 @@ package varint
22

33
import "github.com/golang-infrastructure/go-gtypes"
44

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+
// ---------------------------------------------------------------------------------------------------------------------
628

729
// Encode 对无符号类型进行编码,注意,如果被编码的数字位数较小可能会越编码越大
830
func Encode[T gtypes.Unsigned](value T) []byte {
931
bytes := make([]byte, 0)
32+
33+
// 只要不是读取到了最后一个字节就一直读取
1034
for value > 127 {
11-
bit := (value & 0x7F) | 0x80
35+
bit := (value & 0x7F) | (VarIntNotEndByteHighestBitValue << 7)
1236
value >>= 7
1337
bytes = append(bytes, uint8(bit))
1438
}
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+
1844
return bytes
1945
}
2046

47+
// EncodeSlice 对无符号切片编码,切片中的无符号数字会被挨个存储在返回的字节切片中
2148
func EncodeSlice[T gtypes.Unsigned](valueSlice []T) []byte {
2249
slice := make([]byte, 0)
2350
for _, value := range valueSlice {
@@ -26,7 +53,7 @@ func EncodeSlice[T gtypes.Unsigned](valueSlice []T) []byte {
2653
return slice
2754
}
2855

29-
// ------------------------------------------------ ---------------------------------------------------------------------
56+
// ---------------------------------------------------------------------------------------------------------------------
3057

3158
// Decode 对varint编码的无符号整数进行解码,一次解码一个
3259
func Decode[T gtypes.Unsigned](bytes []byte) T {
@@ -36,25 +63,33 @@ func Decode[T gtypes.Unsigned](bytes []byte) T {
3663
r = r | (T(b&0x7F) << weight)
3764
weight += 7
3865
// 判断是否是最后一个字节,如果是最后一个字节说明当前这个数字读取完毕了
39-
if b&0x80 == 0 {
66+
if b&ByteHighestBit == VarIntEndByteHighestBitValue {
4067
break
4168
}
4269
}
4370
return r
4471
}
4572

46-
// DecodeSlice 解码varint编码的一整个个无符号切片,即一次解码多个
73+
// DecodeSlice 当多个无符号整数放在同一个字节切片中时,可以调用这个方法解码
4774
func DecodeSlice[T gtypes.Unsigned](bytes []byte) []T {
4875
slice := make([]T, 0)
4976
lastIndex := 0
5077
for index, b := range bytes {
51-
if b&0x80 == 0 {
78+
// 当读取到当前无符号整数的最后一个字节的时候,截取当前无符号整数的全部字节传进去解码
79+
if b&ByteHighestBit == VarIntEndByteHighestBitValue {
5280
value := Decode[T](bytes[lastIndex : index+1])
5381
slice = append(slice, value)
5482
lastIndex = index + 1
5583
}
5684
}
85+
86+
// 说明有未读取处理完的内容,将剩下的内容一股脑儿的当做一个数字解码
87+
if lastIndex < len(bytes) {
88+
value := Decode[T](bytes[lastIndex:len(bytes)])
89+
slice = append(slice, value)
90+
}
91+
5792
return slice
5893
}
5994

60-
// ------------------------------------------------ ---------------------------------------------------------------------
95+
// ---------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)