blob: 9d70ab7192e106e3deef0a648c46a12546bb0684 [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001package dynamic
2
3// A reader/writer type that assists with encoding and decoding protobuf's binary representation.
4// This code is largely a fork of proto.Buffer, which cannot be used because it has no exported
5// field or method that provides access to its underlying reader index.
6
7import (
8 "errors"
9 "fmt"
10 "io"
11 "math"
12
13 "github.com/golang/protobuf/proto"
14)
15
16// ErrOverflow is returned when an integer is too large to be represented.
17var ErrOverflow = errors.New("proto: integer overflow")
18
19type codedBuffer struct {
20 buf []byte
21 index int
22}
23
24func newCodedBuffer(buf []byte) *codedBuffer {
25 return &codedBuffer{buf: buf}
26}
27
28func (cb *codedBuffer) reset() {
29 cb.buf = []byte(nil)
30 cb.index = 0
31}
32
33func (cb *codedBuffer) eof() bool {
34 return cb.index >= len(cb.buf)
35}
36
37func (cb *codedBuffer) skip(count int) bool {
38 newIndex := cb.index + count
39 if newIndex > len(cb.buf) {
40 return false
41 }
42 cb.index = newIndex
43 return true
44}
45
46func (cb *codedBuffer) decodeVarintSlow() (x uint64, err error) {
47 i := cb.index
48 l := len(cb.buf)
49
50 for shift := uint(0); shift < 64; shift += 7 {
51 if i >= l {
52 err = io.ErrUnexpectedEOF
53 return
54 }
55 b := cb.buf[i]
56 i++
57 x |= (uint64(b) & 0x7F) << shift
58 if b < 0x80 {
59 cb.index = i
60 return
61 }
62 }
63
64 // The number is too large to represent in a 64-bit value.
65 err = ErrOverflow
66 return
67}
68
69// DecodeVarint reads a varint-encoded integer from the Buffer.
70// This is the format for the
71// int32, int64, uint32, uint64, bool, and enum
72// protocol buffer types.
73func (cb *codedBuffer) decodeVarint() (uint64, error) {
74 i := cb.index
75 buf := cb.buf
76
77 if i >= len(buf) {
78 return 0, io.ErrUnexpectedEOF
79 } else if buf[i] < 0x80 {
80 cb.index++
81 return uint64(buf[i]), nil
82 } else if len(buf)-i < 10 {
83 return cb.decodeVarintSlow()
84 }
85
86 var b uint64
87 // we already checked the first byte
88 x := uint64(buf[i]) - 0x80
89 i++
90
91 b = uint64(buf[i])
92 i++
93 x += b << 7
94 if b&0x80 == 0 {
95 goto done
96 }
97 x -= 0x80 << 7
98
99 b = uint64(buf[i])
100 i++
101 x += b << 14
102 if b&0x80 == 0 {
103 goto done
104 }
105 x -= 0x80 << 14
106
107 b = uint64(buf[i])
108 i++
109 x += b << 21
110 if b&0x80 == 0 {
111 goto done
112 }
113 x -= 0x80 << 21
114
115 b = uint64(buf[i])
116 i++
117 x += b << 28
118 if b&0x80 == 0 {
119 goto done
120 }
121 x -= 0x80 << 28
122
123 b = uint64(buf[i])
124 i++
125 x += b << 35
126 if b&0x80 == 0 {
127 goto done
128 }
129 x -= 0x80 << 35
130
131 b = uint64(buf[i])
132 i++
133 x += b << 42
134 if b&0x80 == 0 {
135 goto done
136 }
137 x -= 0x80 << 42
138
139 b = uint64(buf[i])
140 i++
141 x += b << 49
142 if b&0x80 == 0 {
143 goto done
144 }
145 x -= 0x80 << 49
146
147 b = uint64(buf[i])
148 i++
149 x += b << 56
150 if b&0x80 == 0 {
151 goto done
152 }
153 x -= 0x80 << 56
154
155 b = uint64(buf[i])
156 i++
157 x += b << 63
158 if b&0x80 == 0 {
159 goto done
160 }
161 // x -= 0x80 << 63 // Always zero.
162
163 return 0, ErrOverflow
164
165done:
166 cb.index = i
167 return x, nil
168}
169
170func (cb *codedBuffer) decodeTagAndWireType() (tag int32, wireType int8, err error) {
171 var v uint64
172 v, err = cb.decodeVarint()
173 if err != nil {
174 return
175 }
176 // low 7 bits is wire type
177 wireType = int8(v & 7)
178 // rest is int32 tag number
179 v = v >> 3
180 if v > math.MaxInt32 {
181 err = fmt.Errorf("tag number out of range: %d", v)
182 return
183 }
184 tag = int32(v)
185 return
186}
187
188// DecodeFixed64 reads a 64-bit integer from the Buffer.
189// This is the format for the
190// fixed64, sfixed64, and double protocol buffer types.
191func (cb *codedBuffer) decodeFixed64() (x uint64, err error) {
192 // x, err already 0
193 i := cb.index + 8
194 if i < 0 || i > len(cb.buf) {
195 err = io.ErrUnexpectedEOF
196 return
197 }
198 cb.index = i
199
200 x = uint64(cb.buf[i-8])
201 x |= uint64(cb.buf[i-7]) << 8
202 x |= uint64(cb.buf[i-6]) << 16
203 x |= uint64(cb.buf[i-5]) << 24
204 x |= uint64(cb.buf[i-4]) << 32
205 x |= uint64(cb.buf[i-3]) << 40
206 x |= uint64(cb.buf[i-2]) << 48
207 x |= uint64(cb.buf[i-1]) << 56
208 return
209}
210
211// DecodeFixed32 reads a 32-bit integer from the Buffer.
212// This is the format for the
213// fixed32, sfixed32, and float protocol buffer types.
214func (cb *codedBuffer) decodeFixed32() (x uint64, err error) {
215 // x, err already 0
216 i := cb.index + 4
217 if i < 0 || i > len(cb.buf) {
218 err = io.ErrUnexpectedEOF
219 return
220 }
221 cb.index = i
222
223 x = uint64(cb.buf[i-4])
224 x |= uint64(cb.buf[i-3]) << 8
225 x |= uint64(cb.buf[i-2]) << 16
226 x |= uint64(cb.buf[i-1]) << 24
227 return
228}
229
230func decodeZigZag32(v uint64) int32 {
231 return int32((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31))
232}
233
234func decodeZigZag64(v uint64) int64 {
235 return int64((v >> 1) ^ uint64((int64(v&1)<<63)>>63))
236}
237
238// These are not ValueDecoders: they produce an array of bytes or a string.
239// bytes, embedded messages
240
241// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
242// This is the format used for the bytes protocol buffer
243// type and for embedded messages.
244func (cb *codedBuffer) decodeRawBytes(alloc bool) (buf []byte, err error) {
245 n, err := cb.decodeVarint()
246 if err != nil {
247 return nil, err
248 }
249
250 nb := int(n)
251 if nb < 0 {
252 return nil, fmt.Errorf("proto: bad byte length %d", nb)
253 }
254 end := cb.index + nb
255 if end < cb.index || end > len(cb.buf) {
256 return nil, io.ErrUnexpectedEOF
257 }
258
259 if !alloc {
260 buf = cb.buf[cb.index:end]
261 cb.index += nb
262 return
263 }
264
265 buf = make([]byte, nb)
266 copy(buf, cb.buf[cb.index:])
267 cb.index += nb
268 return
269}
270
271// EncodeVarint writes a varint-encoded integer to the Buffer.
272// This is the format for the
273// int32, int64, uint32, uint64, bool, and enum
274// protocol buffer types.
275func (cb *codedBuffer) encodeVarint(x uint64) error {
276 for x >= 1<<7 {
277 cb.buf = append(cb.buf, uint8(x&0x7f|0x80))
278 x >>= 7
279 }
280 cb.buf = append(cb.buf, uint8(x))
281 return nil
282}
283
284func (cb *codedBuffer) encodeTagAndWireType(tag int32, wireType int8) error {
285 v := uint64((int64(tag) << 3) | int64(wireType))
286 return cb.encodeVarint(v)
287}
288
289// TODO: decodeTagAndWireType
290
291// EncodeFixed64 writes a 64-bit integer to the Buffer.
292// This is the format for the
293// fixed64, sfixed64, and double protocol buffer types.
294func (cb *codedBuffer) encodeFixed64(x uint64) error {
295 cb.buf = append(cb.buf,
296 uint8(x),
297 uint8(x>>8),
298 uint8(x>>16),
299 uint8(x>>24),
300 uint8(x>>32),
301 uint8(x>>40),
302 uint8(x>>48),
303 uint8(x>>56))
304 return nil
305}
306
307// EncodeFixed32 writes a 32-bit integer to the Buffer.
308// This is the format for the
309// fixed32, sfixed32, and float protocol buffer types.
310func (cb *codedBuffer) encodeFixed32(x uint64) error {
311 cb.buf = append(cb.buf,
312 uint8(x),
313 uint8(x>>8),
314 uint8(x>>16),
315 uint8(x>>24))
316 return nil
317}
318
319func encodeZigZag64(v int64) uint64 {
320 return (uint64(v) << 1) ^ uint64(v>>63)
321}
322
323func encodeZigZag32(v int32) uint64 {
324 return uint64((uint32(v) << 1) ^ uint32((v >> 31)))
325}
326
327// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
328// This is the format used for the bytes protocol buffer
329// type and for embedded messages.
330func (cb *codedBuffer) encodeRawBytes(b []byte) error {
331 cb.encodeVarint(uint64(len(b)))
332 cb.buf = append(cb.buf, b...)
333 return nil
334}
335
336func (cb *codedBuffer) encodeMessage(pm proto.Message) error {
337 bytes, err := proto.Marshal(pm)
338 if err != nil {
339 return err
340 }
341 if len(bytes) == 0 {
342 return nil
343 }
344
345 if err := cb.encodeVarint(uint64(len(bytes))); err != nil {
346 return err
347 }
348 cb.buf = append(cb.buf, bytes...)
349 return nil
350}