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