blob: 23045e7d33ab5b7fd36b67855a5161de69ae2f8b [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001package sarama
2
3import (
4 "encoding/binary"
5 "math"
6)
7
8var errInvalidArrayLength = PacketDecodingError{"invalid array length"}
9var errInvalidByteSliceLength = PacketDecodingError{"invalid byteslice length"}
10var errInvalidByteSliceLengthType = PacketDecodingError{"invalid byteslice length type"}
11var errInvalidStringLength = PacketDecodingError{"invalid string length"}
12var errInvalidSubsetSize = PacketDecodingError{"invalid subset size"}
13var errVarintOverflow = PacketDecodingError{"varint overflow"}
14var errInvalidBool = PacketDecodingError{"invalid bool"}
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) getArrayLength() (int, error) {
79 if rd.remaining() < 4 {
80 rd.off = len(rd.raw)
81 return -1, ErrInsufficientData
82 }
83 tmp := int(int32(binary.BigEndian.Uint32(rd.raw[rd.off:])))
84 rd.off += 4
85 if tmp > rd.remaining() {
86 rd.off = len(rd.raw)
87 return -1, ErrInsufficientData
88 } else if tmp > 2*math.MaxUint16 {
89 return -1, errInvalidArrayLength
90 }
91 return tmp, nil
92}
93
94func (rd *realDecoder) getBool() (bool, error) {
95 b, err := rd.getInt8()
96 if err != nil || b == 0 {
97 return false, err
98 }
99 if b != 1 {
100 return false, errInvalidBool
101 }
102 return true, nil
103}
104
105// collections
106
107func (rd *realDecoder) getBytes() ([]byte, error) {
108 tmp, err := rd.getInt32()
109 if err != nil {
110 return nil, err
111 }
112 if tmp == -1 {
113 return nil, nil
114 }
115
116 return rd.getRawBytes(int(tmp))
117}
118
119func (rd *realDecoder) getVarintBytes() ([]byte, error) {
120 tmp, err := rd.getVarint()
121 if err != nil {
122 return nil, err
123 }
124 if tmp == -1 {
125 return nil, nil
126 }
127
128 return rd.getRawBytes(int(tmp))
129}
130
131func (rd *realDecoder) getStringLength() (int, error) {
132 length, err := rd.getInt16()
133 if err != nil {
134 return 0, err
135 }
136
137 n := int(length)
138
139 switch {
140 case n < -1:
141 return 0, errInvalidStringLength
142 case n > rd.remaining():
143 rd.off = len(rd.raw)
144 return 0, ErrInsufficientData
145 }
146
147 return n, nil
148}
149
150func (rd *realDecoder) getString() (string, error) {
151 n, err := rd.getStringLength()
152 if err != nil || n == -1 {
153 return "", err
154 }
155
156 tmpStr := string(rd.raw[rd.off : rd.off+n])
157 rd.off += n
158 return tmpStr, nil
159}
160
161func (rd *realDecoder) getNullableString() (*string, error) {
162 n, err := rd.getStringLength()
163 if err != nil || n == -1 {
164 return nil, err
165 }
166
167 tmpStr := string(rd.raw[rd.off : rd.off+n])
168 rd.off += n
169 return &tmpStr, err
170}
171
172func (rd *realDecoder) getInt32Array() ([]int32, error) {
173 if rd.remaining() < 4 {
174 rd.off = len(rd.raw)
175 return nil, ErrInsufficientData
176 }
177 n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
178 rd.off += 4
179
180 if rd.remaining() < 4*n {
181 rd.off = len(rd.raw)
182 return nil, ErrInsufficientData
183 }
184
185 if n == 0 {
186 return nil, nil
187 }
188
189 if n < 0 {
190 return nil, errInvalidArrayLength
191 }
192
193 ret := make([]int32, n)
194 for i := range ret {
195 ret[i] = int32(binary.BigEndian.Uint32(rd.raw[rd.off:]))
196 rd.off += 4
197 }
198 return ret, nil
199}
200
201func (rd *realDecoder) getInt64Array() ([]int64, error) {
202 if rd.remaining() < 4 {
203 rd.off = len(rd.raw)
204 return nil, ErrInsufficientData
205 }
206 n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
207 rd.off += 4
208
209 if rd.remaining() < 8*n {
210 rd.off = len(rd.raw)
211 return nil, ErrInsufficientData
212 }
213
214 if n == 0 {
215 return nil, nil
216 }
217
218 if n < 0 {
219 return nil, errInvalidArrayLength
220 }
221
222 ret := make([]int64, n)
223 for i := range ret {
224 ret[i] = int64(binary.BigEndian.Uint64(rd.raw[rd.off:]))
225 rd.off += 8
226 }
227 return ret, nil
228}
229
230func (rd *realDecoder) getStringArray() ([]string, error) {
231 if rd.remaining() < 4 {
232 rd.off = len(rd.raw)
233 return nil, ErrInsufficientData
234 }
235 n := int(binary.BigEndian.Uint32(rd.raw[rd.off:]))
236 rd.off += 4
237
238 if n == 0 {
239 return nil, nil
240 }
241
242 if n < 0 {
243 return nil, errInvalidArrayLength
244 }
245
246 ret := make([]string, n)
247 for i := range ret {
248 str, err := rd.getString()
249 if err != nil {
250 return nil, err
251 }
252
253 ret[i] = str
254 }
255 return ret, nil
256}
257
258// subsets
259
260func (rd *realDecoder) remaining() int {
261 return len(rd.raw) - rd.off
262}
263
264func (rd *realDecoder) getSubset(length int) (packetDecoder, error) {
265 buf, err := rd.getRawBytes(length)
266 if err != nil {
267 return nil, err
268 }
269 return &realDecoder{raw: buf}, nil
270}
271
272func (rd *realDecoder) getRawBytes(length int) ([]byte, error) {
273 if length < 0 {
274 return nil, errInvalidByteSliceLength
275 } else if length > rd.remaining() {
276 rd.off = len(rd.raw)
277 return nil, ErrInsufficientData
278 }
279
280 start := rd.off
281 rd.off += length
282 return rd.raw[start:rd.off], nil
283}
284
285func (rd *realDecoder) peek(offset, length int) (packetDecoder, error) {
286 if rd.remaining() < offset+length {
287 return nil, ErrInsufficientData
288 }
289 off := rd.off + offset
290 return &realDecoder{raw: rd.raw[off : off+length]}, nil
291}
292
293// stacks
294
295func (rd *realDecoder) push(in pushDecoder) error {
296 in.saveOffset(rd.off)
297
298 var reserve int
299 if dpd, ok := in.(dynamicPushDecoder); ok {
300 if err := dpd.decode(rd); err != nil {
301 return err
302 }
303 } else {
304 reserve = in.reserveLength()
305 if rd.remaining() < reserve {
306 rd.off = len(rd.raw)
307 return ErrInsufficientData
308 }
309 }
310
311 rd.stack = append(rd.stack, in)
312
313 rd.off += reserve
314
315 return nil
316}
317
318func (rd *realDecoder) pop() error {
319 // this is go's ugly pop pattern (the inverse of append)
320 in := rd.stack[len(rd.stack)-1]
321 rd.stack = rd.stack[:len(rd.stack)-1]
322
323 return in.check(rd.off, rd.raw)
324}