@@ -18,11 +18,14 @@ func (dec *Decoder) readListPack() ([][]byte, []uint32, error) {
18
18
entries := make ([][]byte , 0 , size )
19
19
entrySizes := make ([]uint32 , 0 , size )
20
20
for i := 0 ; i < size ; i ++ {
21
- entry , length , err := dec .readListPackEntry (buf , & cursor )
21
+ str , intval , length , err := dec .readListPackEntry (buf , & cursor )
22
22
if err != nil {
23
23
return nil , nil , err
24
24
}
25
- entries = append (entries , entry )
25
+ if str == nil {
26
+ str = []byte (strconv .FormatInt (intval , 10 ))
27
+ }
28
+ entries = append (entries , str )
26
29
entrySizes = append (entrySizes , length )
27
30
}
28
31
return entries , entrySizes , nil
@@ -37,135 +40,167 @@ func readListPackLength(buf []byte, cursor *int) int {
37
40
return size
38
41
}
39
42
40
- func readVarInt ( buf [] byte , cursor * int ) uint32 {
41
- var v uint32
42
- shift := 0
43
- for * cursor < len ( buf ) {
44
- x := buf [ * cursor ]
45
- * cursor ++
46
- v |= uint32 ( x & 0x7f ) << shift
47
- shift += 7
48
- if x & 0x80 == 0 {
49
- break
50
- }
43
+ func getBackLen ( elementLen uint32 ) uint32 {
44
+ if elementLen <= 127 {
45
+ return 1
46
+ } else if elementLen < ( 1 << 14 ) - 1 {
47
+ return 2
48
+ } else if elementLen < ( 1 << 21 ) - 1 {
49
+ return 3
50
+ } else if elementLen < ( 1 << 28 ) - 1 {
51
+ return 4
52
+ } else {
53
+ return 5
51
54
}
52
- return v
53
55
}
54
56
55
- // readListPackEntry returns: content(string), length, error
56
- func (dec * Decoder ) readListPackEntry (buf []byte , cursor * int ) ([]byte , uint32 , error ) {
57
+
58
+ // readListPackEntry returns: string content, int content, entry length(encoding+content+backlen), error
59
+ func (dec * Decoder ) readListPackEntry (buf []byte , cursor * int ) ([]byte , int64 , uint32 , error ) {
57
60
header , err := readByte (buf , cursor )
58
61
if err != nil {
59
- return nil , 0 , err
62
+ return nil , 0 , 0 , err
60
63
}
61
- var result []byte
62
- var length uint32
63
64
switch header >> 6 {
64
- case 0 , 1 : // 0xxx xxxx -> uint7 [0, 127]
65
- result = []byte (strconv .FormatInt (int64 (int8 (header )), 10 ))
66
- length = readVarInt (buf , cursor ) // read element length
67
- return result , length , nil
68
- case 2 : // 10xx xxxx -> str, len<= 63
65
+ case 0 , 1 : // 0xxxxxxx, uint7
66
+ result := int64 (int8 (header ))
67
+ var contentLen uint32 = 1
68
+ backlen := getBackLen (contentLen )
69
+ * cursor += int (backlen )
70
+ return nil , result , contentLen + backlen , nil
71
+ case 2 : // 10xxxxxx + content, string(len<=63)
69
72
strLen := int (header & 0x3f )
70
73
result , err := readBytes (buf , cursor , strLen )
71
74
if err != nil {
72
- return nil , 0 , err
75
+ return nil , 0 , 0 , err
73
76
}
74
- length = readVarInt (buf , cursor ) // read element length
75
- return result , length , nil
77
+ var contentLen = uint32 (1 + strLen )
78
+ backlen := getBackLen (contentLen )
79
+ * cursor += int (backlen )
80
+ return result , 0 , contentLen + backlen , nil
76
81
}
77
- // assert header == 11xx xxxx
82
+ // assert header == 11xxxxxx
78
83
switch header >> 4 {
79
- case 12 , 13 : // 110x xxxx -> int13
84
+ case 12 , 13 : // 110xxxxx yyyyyyyy, int13
80
85
// see https://github.com/CN-annotation-team/redis7.0-chinese-annotated/blob/fba43c524524cbdb54955a28af228b513420d78d/src/listpack.c#L586
81
86
next , err := readByte (buf , cursor )
82
87
if err != nil {
83
- return nil , 0 , err
88
+ return nil , 0 , 0 , err
84
89
}
85
90
val := ((uint (header ) & 0x1F ) << 8 ) | uint (next )
86
91
if val >= uint (1 << 12 ) {
87
92
val = - (8191 - val ) - 1 // val is uint, must use -(8191 - val), val - 8191 will cause overflow
88
93
}
89
- result = []byte (strconv .FormatInt (int64 (val ), 10 ))
90
- length = readVarInt (buf , cursor ) // read element length
91
- return result , length , nil
92
- case 14 : // 1110 xxxx -> str, type(len) == uint12
94
+ result := int64 (val )
95
+ var contentLen uint32 = 2
96
+ backlen := getBackLen (contentLen )
97
+ * cursor += int (backlen )
98
+ return nil , result , contentLen + backlen , nil
99
+ case 14 : // 1110xxxx yyyyyyyy + content, string(len < 1<<12)
93
100
dec .buffer [0 ] = header & 0x0f
94
101
dec .buffer [1 ], err = readByte (buf , cursor )
102
+ if err != nil {
103
+ return nil , 0 , 0 , err
104
+ }
95
105
strLen := binary .BigEndian .Uint16 (dec .buffer [:2 ])
96
106
result , err := readBytes (buf , cursor , int (strLen ))
97
107
if err != nil {
98
- return nil , 0 , err
108
+ return nil , 0 , 0 , err
99
109
}
100
- length = readVarInt (buf , cursor ) // read element length
101
- return result , length , nil
110
+ var contentLen = uint32 (2 + strLen )
111
+ backlen := getBackLen (contentLen )
112
+ * cursor += int (backlen )
113
+ return result , 0 , contentLen + backlen , nil
102
114
}
103
- // assert header == 1111 xxxx
115
+ // assert header == 1111xxxx
104
116
switch header & 0x0f {
105
- case 0 : // 1111 0000 -> str, 4 bytes len
117
+ case 0 : // 11110000 aaaaaaaa bbbbbbbb cccccccc dddddddd + content, string( len < 1<<32)
106
118
var lenBytes []byte
107
119
lenBytes , err = readBytes (buf , cursor , 4 )
108
120
if err != nil {
109
- return nil , 0 , err
121
+ return nil , 0 , 0 , err
110
122
}
111
123
strLen := int (binary .LittleEndian .Uint32 (lenBytes ))
112
124
result , err := readBytes (buf , cursor , strLen )
113
125
if err != nil {
114
- return nil , 0 , err
126
+ return nil , 0 , 0 , err
115
127
}
116
- length = readVarInt (buf , cursor ) // read element length
117
- return result , length , nil
118
- case 1 : // 1111 0001 -> int16
128
+ var contentLen = uint32 (1 + 4 + strLen )
129
+ backlen := getBackLen (contentLen )
130
+ * cursor += int (backlen )
131
+ return result , 0 , contentLen + backlen , nil
132
+ case 1 : // 11110001 aaaaaaaa bbbbbbbb, int16
119
133
var bs []byte
120
134
bs , err = readBytes (buf , cursor , 2 )
121
135
if err != nil {
122
- return nil , 0 , err
136
+ return nil , 0 , 0 , err
123
137
}
124
- result = []byte (strconv .FormatInt (int64 (int16 (binary .LittleEndian .Uint16 (bs ))), 10 ))
125
- length = readVarInt (buf , cursor )
126
- return result , length , nil
127
- case 2 : // 1111 0010 -> int24
138
+ result := int64 (int16 (binary .LittleEndian .Uint16 (bs )))
139
+ var contentLen uint32 = 3
140
+ backlen := getBackLen (contentLen )
141
+ * cursor += int (backlen )
142
+ return nil , result , contentLen + backlen , nil
143
+ case 2 : // 11110010 aaaaaaaa bbbbbbbb cccccccc, int24
128
144
var bs []byte
129
145
bs , err = readBytes (buf , cursor , 3 )
130
146
if err != nil {
131
- return nil , 0 , err
147
+ return nil , 0 , 0 , err
132
148
}
133
149
bs = append ([]byte {0 }, bs ... )
134
- result = []byte (strconv .FormatInt (int64 (int32 (binary .LittleEndian .Uint32 (bs ))>> 8 ), 10 ))
135
- length = readVarInt (buf , cursor )
136
- return result , length , nil
150
+ result := int64 (int32 (binary .LittleEndian .Uint32 (bs ))>> 8 )
151
+ var contentLen uint32 = 4
152
+ backlen := getBackLen (contentLen )
153
+ * cursor += int (backlen )
154
+ return nil , result , contentLen + backlen , nil
137
155
case 3 : // 1111 0011 -> int32
138
156
var bs []byte
139
157
bs , err = readBytes (buf , cursor , 4 )
140
158
if err != nil {
141
- return nil , 0 , err
159
+ return nil , 0 , 0 , err
142
160
}
143
- result = []byte (strconv .FormatInt (int64 (int32 (binary .LittleEndian .Uint32 (bs ))), 10 ))
144
- length = readVarInt (buf , cursor )
145
- return result , length , nil
146
- case 4 : // 1111 0100 -> int64
161
+ result := int64 (int32 (binary .LittleEndian .Uint32 (bs )))
162
+ var contentLen uint32 = 5
163
+ backlen := getBackLen (contentLen )
164
+ * cursor += int (backlen )
165
+ return nil , result , contentLen + backlen , nil
166
+ case 4 : // 11110100 8Byte -> int64
147
167
var bs []byte
148
168
bs , err = readBytes (buf , cursor , 8 )
149
169
if err != nil {
150
- return nil , 0 , err
170
+ return nil , 0 , 0 , err
151
171
}
152
- result = []byte (strconv .FormatInt (int64 (binary .LittleEndian .Uint64 (bs )), 10 ))
153
- length = readVarInt (buf , cursor )
154
- return result , length , nil
155
- case 15 : // 1111 1111 -> end
156
- return nil , 0 , errors .New ("unexpected end" )
172
+ result := int64 (binary .LittleEndian .Uint64 (bs ))
173
+ var contentLen uint32 = 9
174
+ backlen := getBackLen (contentLen )
175
+ * cursor += int (backlen )
176
+ return nil , result , contentLen + backlen , nil
177
+ case 15 : // 11111111 -> end
178
+ return nil , 0 , 0 , errors .New ("unexpected end" )
157
179
}
158
- return nil , 0 , fmt .Errorf ("unknown entry header" )
180
+ return nil , 0 , 0 , fmt .Errorf ("unknown entry header" )
181
+ }
182
+
183
+ // readListPackEntryAsString return a string representation of entry
184
+ // It means if the entry is a integer, then format it as string
185
+ func (dec * Decoder ) readListPackEntryAsString (buf []byte , cursor * int ) ([]byte , error ) {
186
+ str , intval , _ , err := dec .readListPackEntry (buf , cursor )
187
+ if err != nil {
188
+ return nil , fmt .Errorf ("read from failed: %v" , err )
189
+ }
190
+ if str != nil {
191
+ return str , nil
192
+ }
193
+ str = []byte (strconv .FormatInt (intval , 10 ))
194
+ return str , nil
159
195
}
160
196
161
197
func (dec * Decoder ) readListPackEntryAsInt (buf []byte , cursor * int ) (int64 , error ) {
162
- bin , _ , err := dec .readListPackEntry (buf , cursor )
198
+ str , intval , _ , err := dec .readListPackEntry (buf , cursor )
163
199
if err != nil {
164
200
return 0 , fmt .Errorf ("read from failed: %v" , err )
165
201
}
166
- i , err := strconv .ParseInt (string (bin ), 10 , 64 )
167
- if err != nil {
168
- return 0 , fmt .Errorf ("%s is not a uint" , string (bin ))
202
+ if str != nil {
203
+ return 0 , fmt .Errorf ("%s is not a integer" , string (str ))
169
204
}
170
- return i , nil
205
+ return intval , nil
171
206
}
0 commit comments