blob: 2482c637763b305424ed584d7adf7049f2a6213c [file] [log] [blame]
khenaidooac637102019-01-14 15:44:34 -05001package sarama
2
3import (
4 "encoding/binary"
5 "math"
6)
7
khenaidood948f772021-08-11 17:49:24 -04008var (
9 errInvalidArrayLength = PacketDecodingError{"invalid array length"}
10 errInvalidByteSliceLength = PacketDecodingError{"invalid byteslice length"}
11 errInvalidStringLength = PacketDecodingError{"invalid string length"}
12 errVarintOverflow = PacketDecodingError{"varint overflow"}
13 errUVarintOverflow = PacketDecodingError{"uvarint overflow"}
14 errInvalidBool = PacketDecodingError{"invalid bool"}
15 errUnsupportedTaggedFields = PacketDecodingError{"non-empty tagged fields are not supported yet"}
16)
khenaidooac637102019-01-14 15:44:34 -050017
18type realDecoder struct {
19 raw []byte
20 off int
21 stack []pushDecoder
22}
23
24// primitives
25
26func (rd *realDecoder) getInt8() (int8, error) {
27 if rd.remaining() < 1 {
28 rd.off = len(rd.raw)
29 return -1, ErrInsufficientData
30 }
31 tmp := int8(rd.raw[rd.off])
32 rd.off++
33 return tmp, nil
34}
35
36func (rd *realDecoder) getInt16() (int16, error) {
37 if rd.remaining() < 2 {
38 rd.off = len(rd.raw)
39 return -1, ErrInsufficientData
40 }
41 tmp := int16(binary.BigEndian.Uint16(rd.raw[rd.off:]))
42 rd.off += 2
43 return tmp, nil
44}
45
46func (rd *realDecoder) getInt32() (int32, error) {
47 if rd.remaining() < 4 {
48 rd.off = len(rd.raw)
49 return -1, ErrInsufficientData
50 }
51 tmp := int32(binary.BigEndian.Uint32(rd.raw[rd.off:]))
52 rd.off += 4
53 return tmp, nil
54}
55
56func (rd *realDecoder) getInt64() (int64, error) {
57 if rd.remaining() < 8 {
58 rd.off = len(rd.raw)
59 return -1, ErrInsufficientData
60 }
61 tmp := int64(binary.BigEndian.Uint64(rd.raw[rd.off:]))
62 rd.off += 8
63 return tmp, nil
64}
65
66func (rd *realDecoder) getVarint() (int64, error) {
67 tmp, n := binary.Varint(rd.raw[rd.off:])
68 if n == 0 {
69 rd.off = len(rd.raw)
70 return -1, ErrInsufficientData
71 }
72 if n < 0 {
73 rd.off -= n
74 return -1, errVarintOverflow
75 }
76 rd.off += n
77 return tmp, nil
78}
79
khenaidood948f772021-08-11 17:49:24 -040080func (rd *realDecoder) getUVarint() (uint64, error) {
81 tmp, n := binary.Uvarint(rd.raw[rd.off:])
82 if n == 0 {
83 rd.off = len(rd.raw)
84 return 0, ErrInsufficientData
85 }
86
87 if n < 0 {
88 rd.off -= n
89 return 0, errUVarintOverflow
90 }
91
92 rd.off += n
93 return tmp, nil
94}
95
khenaidooac637102019-01-14 15:44:34 -050096func (rd *realDecoder) getArrayLength() (int, error) {
97 if rd.remaining() < 4 {
98 rd.off = len(rd.raw)
99 return -1, ErrInsufficientData
100 }
101 tmp := int(int32(binary.BigEndian.Uint32(rd.raw[rd.off:])))
102 rd.off += 4
103 if tmp > rd.remaining() {
104 rd.off = len(rd.raw)
105 return -1, ErrInsufficientData
106 } else if tmp > 2*math.MaxUint16 {
107 return -1, errInvalidArrayLength
108 }
109 return tmp, nil
110}
111
khenaidood948f772021-08-11 17:49:24 -0400112func (rd *realDecoder) getCompactArrayLength() (int, error) {
113 n, err := rd.getUVarint()
114 if err != nil {
115 return 0, err
116 }
117
118 if n == 0 {
119 return 0, nil
120 }
121
122 return int(n) - 1, nil
123}
124
khenaidooac637102019-01-14 15:44:34 -0500125func (rd *realDecoder) getBool() (bool, error) {
126 b, err := rd.getInt8()
127 if err != nil || b == 0 {
128 return false, err
129 }
130 if b != 1 {
131 return false, errInvalidBool
132 }
133 return true, nil
134}
135
khenaidood948f772021-08-11 17:49:24 -0400136func (rd *realDecoder) getEmptyTaggedFieldArray() (int, error) {
137 tagCount, err := rd.getUVarint()
138 if err != nil {
139 return 0, err
140 }
141
142 if tagCount != 0 {
143 return 0, errUnsupportedTaggedFields
144 }
145
146 return 0, nil
147}
148
khenaidooac637102019-01-14 15:44:34 -0500149// collections
150
151func (rd *realDecoder) getBytes() ([]byte, error) {
152 tmp, err := rd.getInt32()
153 if err != nil {
154 return nil, err
155 }
156 if tmp == -1 {
157 return nil, nil
158 }
159
160 return rd.getRawBytes(int(tmp))
161}
162
163func (rd *realDecoder) getVarintBytes() ([]byte, error) {
164 tmp, err := rd.getVarint()
165 if err != nil {
166 return nil, err
167 }
168 if tmp == -1 {
169 return nil, nil
170 }
171
172 return rd.getRawBytes(int(tmp))
173}
174
khenaidood948f772021-08-11 17:49:24 -0400175func (rd *realDecoder) getCompactBytes() ([]byte, error) {
176 n, err := rd.getUVarint()
177 if err != nil {
178 return nil, err
179 }
180
181 length := int(n - 1)
182 return rd.getRawBytes(length)
183}
184
khenaidooac637102019-01-14 15:44:34 -0500185func (rd *realDecoder) getStringLength() (int, error) {
186 length, err := rd.getInt16()
187 if err != nil {
188 return 0, err
189 }
190
191 n := int(length)
192
193 switch {
194 case n < -1:
195 return 0, errInvalidStringLength
196 case n > rd.remaining():
197 rd.off = len(rd.raw)
198 return 0, ErrInsufficientData
199 }
200
201 return n, nil
202}
203
204func (rd *realDecoder) getString() (string, error) {
205 n, err := rd.getStringLength()
206 if err != nil || n == -1 {
207 return "", err
208 }
209
210 tmpStr := string(rd.raw[rd.off : rd.off+n])
211 rd.off += n
212 return tmpStr, nil
213}
214
215func (rd *realDecoder) getNullableString() (*string, error) {
216 n, err := rd.getStringLength()
217 if err != nil || n == -1 {
218 return nil, err
219 }
220
221 tmpStr := string(rd.raw[rd.off : rd.off+n])
222 rd.off += n
223 return &tmpStr, err
224}
225
khenaidood948f772021-08-11 17:49:24 -0400226func (rd *realDecoder) getCompactString() (string, error) {
227 n, err := rd.getUVarint()
228 if err != nil {
229 return "", err
230 }
231
232 length := int(n - 1)
233
234 tmpStr := string(rd.raw[rd.off : rd.off+length])
235 rd.off += length
236 return tmpStr, nil
237}
238
239func (rd *realDecoder) getCompactNullableString() (*string, error) {
240 n, err := rd.getUVarint()
241 if err != nil {
242 return nil, err
243 }
244
245 length := int(n - 1)
246
247 if length < 0 {
248 return nil, err
249 }
250
251 tmpStr := string(rd.raw[rd.off : rd.off+length])
252 rd.off += length
253 return &tmpStr, err
254}
255
256func (rd *realDecoder) getCompactInt32Array() ([]int32, error) {
257 n, err := rd.getUVarint()
258 if err != nil {
259 return nil, err
260 }
261
262 if n == 0 {
263 return nil, nil
264 }
265
266 arrayLength := int(n) - 1
267
268 ret := make([]int32, arrayLength)
269
270 for i := range ret {
271 ret[i] = int32(binary.BigEndian.Uint32(rd.raw[rd.off:]))
272 rd.off += 4
273 }
274 return ret, nil
275}
276
khenaidooac637102019-01-14 15:44:34 -0500277func (rd *realDecoder) getInt32Array() ([]int32, error) {
278 if rd.remaining() < 4 {
279 rd.off = len(rd.raw)
280 return nil, ErrInsufficientData
281 }
282 n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
283 rd.off += 4
284
285 if rd.remaining() < 4*n {
286 rd.off = len(rd.raw)
287 return nil, ErrInsufficientData
288 }
289
290 if n == 0 {
291 return nil, nil
292 }
293
294 if n < 0 {
295 return nil, errInvalidArrayLength
296 }
297
298 ret := make([]int32, n)
299 for i := range ret {
300 ret[i] = int32(binary.BigEndian.Uint32(rd.raw[rd.off:]))
301 rd.off += 4
302 }
303 return ret, nil
304}
305
306func (rd *realDecoder) getInt64Array() ([]int64, error) {
307 if rd.remaining() < 4 {
308 rd.off = len(rd.raw)
309 return nil, ErrInsufficientData
310 }
311 n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
312 rd.off += 4
313
314 if rd.remaining() < 8*n {
315 rd.off = len(rd.raw)
316 return nil, ErrInsufficientData
317 }
318
319 if n == 0 {
320 return nil, nil
321 }
322
323 if n < 0 {
324 return nil, errInvalidArrayLength
325 }
326
327 ret := make([]int64, n)
328 for i := range ret {
329 ret[i] = int64(binary.BigEndian.Uint64(rd.raw[rd.off:]))
330 rd.off += 8
331 }
332 return ret, nil
333}
334
335func (rd *realDecoder) getStringArray() ([]string, error) {
336 if rd.remaining() < 4 {
337 rd.off = len(rd.raw)
338 return nil, ErrInsufficientData
339 }
340 n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
341 rd.off += 4
342
343 if n == 0 {
344 return nil, nil
345 }
346
347 if n < 0 {
348 return nil, errInvalidArrayLength
349 }
350
351 ret := make([]string, n)
352 for i := range ret {
353 str, err := rd.getString()
354 if err != nil {
355 return nil, err
356 }
357
358 ret[i] = str
359 }
360 return ret, nil
361}
362
363// subsets
364
365func (rd *realDecoder) remaining() int {
366 return len(rd.raw) - rd.off
367}
368
369func (rd *realDecoder) getSubset(length int) (packetDecoder, error) {
370 buf, err := rd.getRawBytes(length)
371 if err != nil {
372 return nil, err
373 }
374 return &realDecoder{raw: buf}, nil
375}
376
377func (rd *realDecoder) getRawBytes(length int) ([]byte, error) {
378 if length < 0 {
379 return nil, errInvalidByteSliceLength
380 } else if length > rd.remaining() {
381 rd.off = len(rd.raw)
382 return nil, ErrInsufficientData
383 }
384
385 start := rd.off
386 rd.off += length
387 return rd.raw[start:rd.off], nil
388}
389
390func (rd *realDecoder) peek(offset, length int) (packetDecoder, error) {
391 if rd.remaining() < offset+length {
392 return nil, ErrInsufficientData
393 }
394 off := rd.off + offset
395 return &realDecoder{raw: rd.raw[off : off+length]}, nil
396}
397
Scott Baker8461e152019-10-01 14:44:30 -0700398func (rd *realDecoder) peekInt8(offset int) (int8, error) {
399 const byteLen = 1
400 if rd.remaining() < offset+byteLen {
401 return -1, ErrInsufficientData
402 }
403 return int8(rd.raw[rd.off+offset]), nil
404}
405
khenaidooac637102019-01-14 15:44:34 -0500406// stacks
407
408func (rd *realDecoder) push(in pushDecoder) error {
409 in.saveOffset(rd.off)
410
411 var reserve int
412 if dpd, ok := in.(dynamicPushDecoder); ok {
413 if err := dpd.decode(rd); err != nil {
414 return err
415 }
416 } else {
417 reserve = in.reserveLength()
418 if rd.remaining() < reserve {
419 rd.off = len(rd.raw)
420 return ErrInsufficientData
421 }
422 }
423
424 rd.stack = append(rd.stack, in)
425
426 rd.off += reserve
427
428 return nil
429}
430
431func (rd *realDecoder) pop() error {
432 // this is go's ugly pop pattern (the inverse of append)
433 in := rd.stack[len(rd.stack)-1]
434 rd.stack = rd.stack[:len(rd.stack)-1]
435
436 return in.check(rd.off, rd.raw)
437}