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