xref: /aosp_15_r20/external/golang-protobuf/encoding/protowire/wire.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsen// Package protowire parses and formats the raw wire encoding.
6*1c12ee1eSDan Willemsen// See https://protobuf.dev/programming-guides/encoding.
7*1c12ee1eSDan Willemsen//
8*1c12ee1eSDan Willemsen// For marshaling and unmarshaling entire protobuf messages,
9*1c12ee1eSDan Willemsen// use the "google.golang.org/protobuf/proto" package instead.
10*1c12ee1eSDan Willemsenpackage protowire
11*1c12ee1eSDan Willemsen
12*1c12ee1eSDan Willemsenimport (
13*1c12ee1eSDan Willemsen	"io"
14*1c12ee1eSDan Willemsen	"math"
15*1c12ee1eSDan Willemsen	"math/bits"
16*1c12ee1eSDan Willemsen
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/errors"
18*1c12ee1eSDan Willemsen)
19*1c12ee1eSDan Willemsen
20*1c12ee1eSDan Willemsen// Number represents the field number.
21*1c12ee1eSDan Willemsentype Number int32
22*1c12ee1eSDan Willemsen
23*1c12ee1eSDan Willemsenconst (
24*1c12ee1eSDan Willemsen	MinValidNumber        Number = 1
25*1c12ee1eSDan Willemsen	FirstReservedNumber   Number = 19000
26*1c12ee1eSDan Willemsen	LastReservedNumber    Number = 19999
27*1c12ee1eSDan Willemsen	MaxValidNumber        Number = 1<<29 - 1
28*1c12ee1eSDan Willemsen	DefaultRecursionLimit        = 10000
29*1c12ee1eSDan Willemsen)
30*1c12ee1eSDan Willemsen
31*1c12ee1eSDan Willemsen// IsValid reports whether the field number is semantically valid.
32*1c12ee1eSDan Willemsenfunc (n Number) IsValid() bool {
33*1c12ee1eSDan Willemsen	return MinValidNumber <= n && n <= MaxValidNumber
34*1c12ee1eSDan Willemsen}
35*1c12ee1eSDan Willemsen
36*1c12ee1eSDan Willemsen// Type represents the wire type.
37*1c12ee1eSDan Willemsentype Type int8
38*1c12ee1eSDan Willemsen
39*1c12ee1eSDan Willemsenconst (
40*1c12ee1eSDan Willemsen	VarintType     Type = 0
41*1c12ee1eSDan Willemsen	Fixed32Type    Type = 5
42*1c12ee1eSDan Willemsen	Fixed64Type    Type = 1
43*1c12ee1eSDan Willemsen	BytesType      Type = 2
44*1c12ee1eSDan Willemsen	StartGroupType Type = 3
45*1c12ee1eSDan Willemsen	EndGroupType   Type = 4
46*1c12ee1eSDan Willemsen)
47*1c12ee1eSDan Willemsen
48*1c12ee1eSDan Willemsenconst (
49*1c12ee1eSDan Willemsen	_ = -iota
50*1c12ee1eSDan Willemsen	errCodeTruncated
51*1c12ee1eSDan Willemsen	errCodeFieldNumber
52*1c12ee1eSDan Willemsen	errCodeOverflow
53*1c12ee1eSDan Willemsen	errCodeReserved
54*1c12ee1eSDan Willemsen	errCodeEndGroup
55*1c12ee1eSDan Willemsen	errCodeRecursionDepth
56*1c12ee1eSDan Willemsen)
57*1c12ee1eSDan Willemsen
58*1c12ee1eSDan Willemsenvar (
59*1c12ee1eSDan Willemsen	errFieldNumber = errors.New("invalid field number")
60*1c12ee1eSDan Willemsen	errOverflow    = errors.New("variable length integer overflow")
61*1c12ee1eSDan Willemsen	errReserved    = errors.New("cannot parse reserved wire type")
62*1c12ee1eSDan Willemsen	errEndGroup    = errors.New("mismatching end group marker")
63*1c12ee1eSDan Willemsen	errParse       = errors.New("parse error")
64*1c12ee1eSDan Willemsen)
65*1c12ee1eSDan Willemsen
66*1c12ee1eSDan Willemsen// ParseError converts an error code into an error value.
67*1c12ee1eSDan Willemsen// This returns nil if n is a non-negative number.
68*1c12ee1eSDan Willemsenfunc ParseError(n int) error {
69*1c12ee1eSDan Willemsen	if n >= 0 {
70*1c12ee1eSDan Willemsen		return nil
71*1c12ee1eSDan Willemsen	}
72*1c12ee1eSDan Willemsen	switch n {
73*1c12ee1eSDan Willemsen	case errCodeTruncated:
74*1c12ee1eSDan Willemsen		return io.ErrUnexpectedEOF
75*1c12ee1eSDan Willemsen	case errCodeFieldNumber:
76*1c12ee1eSDan Willemsen		return errFieldNumber
77*1c12ee1eSDan Willemsen	case errCodeOverflow:
78*1c12ee1eSDan Willemsen		return errOverflow
79*1c12ee1eSDan Willemsen	case errCodeReserved:
80*1c12ee1eSDan Willemsen		return errReserved
81*1c12ee1eSDan Willemsen	case errCodeEndGroup:
82*1c12ee1eSDan Willemsen		return errEndGroup
83*1c12ee1eSDan Willemsen	default:
84*1c12ee1eSDan Willemsen		return errParse
85*1c12ee1eSDan Willemsen	}
86*1c12ee1eSDan Willemsen}
87*1c12ee1eSDan Willemsen
88*1c12ee1eSDan Willemsen// ConsumeField parses an entire field record (both tag and value) and returns
89*1c12ee1eSDan Willemsen// the field number, the wire type, and the total length.
90*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
91*1c12ee1eSDan Willemsen//
92*1c12ee1eSDan Willemsen// The total length includes the tag header and the end group marker (if the
93*1c12ee1eSDan Willemsen// field is a group).
94*1c12ee1eSDan Willemsenfunc ConsumeField(b []byte) (Number, Type, int) {
95*1c12ee1eSDan Willemsen	num, typ, n := ConsumeTag(b)
96*1c12ee1eSDan Willemsen	if n < 0 {
97*1c12ee1eSDan Willemsen		return 0, 0, n // forward error code
98*1c12ee1eSDan Willemsen	}
99*1c12ee1eSDan Willemsen	m := ConsumeFieldValue(num, typ, b[n:])
100*1c12ee1eSDan Willemsen	if m < 0 {
101*1c12ee1eSDan Willemsen		return 0, 0, m // forward error code
102*1c12ee1eSDan Willemsen	}
103*1c12ee1eSDan Willemsen	return num, typ, n + m
104*1c12ee1eSDan Willemsen}
105*1c12ee1eSDan Willemsen
106*1c12ee1eSDan Willemsen// ConsumeFieldValue parses a field value and returns its length.
107*1c12ee1eSDan Willemsen// This assumes that the field Number and wire Type have already been parsed.
108*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
109*1c12ee1eSDan Willemsen//
110*1c12ee1eSDan Willemsen// When parsing a group, the length includes the end group marker and
111*1c12ee1eSDan Willemsen// the end group is verified to match the starting field number.
112*1c12ee1eSDan Willemsenfunc ConsumeFieldValue(num Number, typ Type, b []byte) (n int) {
113*1c12ee1eSDan Willemsen	return consumeFieldValueD(num, typ, b, DefaultRecursionLimit)
114*1c12ee1eSDan Willemsen}
115*1c12ee1eSDan Willemsen
116*1c12ee1eSDan Willemsenfunc consumeFieldValueD(num Number, typ Type, b []byte, depth int) (n int) {
117*1c12ee1eSDan Willemsen	switch typ {
118*1c12ee1eSDan Willemsen	case VarintType:
119*1c12ee1eSDan Willemsen		_, n = ConsumeVarint(b)
120*1c12ee1eSDan Willemsen		return n
121*1c12ee1eSDan Willemsen	case Fixed32Type:
122*1c12ee1eSDan Willemsen		_, n = ConsumeFixed32(b)
123*1c12ee1eSDan Willemsen		return n
124*1c12ee1eSDan Willemsen	case Fixed64Type:
125*1c12ee1eSDan Willemsen		_, n = ConsumeFixed64(b)
126*1c12ee1eSDan Willemsen		return n
127*1c12ee1eSDan Willemsen	case BytesType:
128*1c12ee1eSDan Willemsen		_, n = ConsumeBytes(b)
129*1c12ee1eSDan Willemsen		return n
130*1c12ee1eSDan Willemsen	case StartGroupType:
131*1c12ee1eSDan Willemsen		if depth < 0 {
132*1c12ee1eSDan Willemsen			return errCodeRecursionDepth
133*1c12ee1eSDan Willemsen		}
134*1c12ee1eSDan Willemsen		n0 := len(b)
135*1c12ee1eSDan Willemsen		for {
136*1c12ee1eSDan Willemsen			num2, typ2, n := ConsumeTag(b)
137*1c12ee1eSDan Willemsen			if n < 0 {
138*1c12ee1eSDan Willemsen				return n // forward error code
139*1c12ee1eSDan Willemsen			}
140*1c12ee1eSDan Willemsen			b = b[n:]
141*1c12ee1eSDan Willemsen			if typ2 == EndGroupType {
142*1c12ee1eSDan Willemsen				if num != num2 {
143*1c12ee1eSDan Willemsen					return errCodeEndGroup
144*1c12ee1eSDan Willemsen				}
145*1c12ee1eSDan Willemsen				return n0 - len(b)
146*1c12ee1eSDan Willemsen			}
147*1c12ee1eSDan Willemsen
148*1c12ee1eSDan Willemsen			n = consumeFieldValueD(num2, typ2, b, depth-1)
149*1c12ee1eSDan Willemsen			if n < 0 {
150*1c12ee1eSDan Willemsen				return n // forward error code
151*1c12ee1eSDan Willemsen			}
152*1c12ee1eSDan Willemsen			b = b[n:]
153*1c12ee1eSDan Willemsen		}
154*1c12ee1eSDan Willemsen	case EndGroupType:
155*1c12ee1eSDan Willemsen		return errCodeEndGroup
156*1c12ee1eSDan Willemsen	default:
157*1c12ee1eSDan Willemsen		return errCodeReserved
158*1c12ee1eSDan Willemsen	}
159*1c12ee1eSDan Willemsen}
160*1c12ee1eSDan Willemsen
161*1c12ee1eSDan Willemsen// AppendTag encodes num and typ as a varint-encoded tag and appends it to b.
162*1c12ee1eSDan Willemsenfunc AppendTag(b []byte, num Number, typ Type) []byte {
163*1c12ee1eSDan Willemsen	return AppendVarint(b, EncodeTag(num, typ))
164*1c12ee1eSDan Willemsen}
165*1c12ee1eSDan Willemsen
166*1c12ee1eSDan Willemsen// ConsumeTag parses b as a varint-encoded tag, reporting its length.
167*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
168*1c12ee1eSDan Willemsenfunc ConsumeTag(b []byte) (Number, Type, int) {
169*1c12ee1eSDan Willemsen	v, n := ConsumeVarint(b)
170*1c12ee1eSDan Willemsen	if n < 0 {
171*1c12ee1eSDan Willemsen		return 0, 0, n // forward error code
172*1c12ee1eSDan Willemsen	}
173*1c12ee1eSDan Willemsen	num, typ := DecodeTag(v)
174*1c12ee1eSDan Willemsen	if num < MinValidNumber {
175*1c12ee1eSDan Willemsen		return 0, 0, errCodeFieldNumber
176*1c12ee1eSDan Willemsen	}
177*1c12ee1eSDan Willemsen	return num, typ, n
178*1c12ee1eSDan Willemsen}
179*1c12ee1eSDan Willemsen
180*1c12ee1eSDan Willemsenfunc SizeTag(num Number) int {
181*1c12ee1eSDan Willemsen	return SizeVarint(EncodeTag(num, 0)) // wire type has no effect on size
182*1c12ee1eSDan Willemsen}
183*1c12ee1eSDan Willemsen
184*1c12ee1eSDan Willemsen// AppendVarint appends v to b as a varint-encoded uint64.
185*1c12ee1eSDan Willemsenfunc AppendVarint(b []byte, v uint64) []byte {
186*1c12ee1eSDan Willemsen	switch {
187*1c12ee1eSDan Willemsen	case v < 1<<7:
188*1c12ee1eSDan Willemsen		b = append(b, byte(v))
189*1c12ee1eSDan Willemsen	case v < 1<<14:
190*1c12ee1eSDan Willemsen		b = append(b,
191*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
192*1c12ee1eSDan Willemsen			byte(v>>7))
193*1c12ee1eSDan Willemsen	case v < 1<<21:
194*1c12ee1eSDan Willemsen		b = append(b,
195*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
196*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
197*1c12ee1eSDan Willemsen			byte(v>>14))
198*1c12ee1eSDan Willemsen	case v < 1<<28:
199*1c12ee1eSDan Willemsen		b = append(b,
200*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
201*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
202*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
203*1c12ee1eSDan Willemsen			byte(v>>21))
204*1c12ee1eSDan Willemsen	case v < 1<<35:
205*1c12ee1eSDan Willemsen		b = append(b,
206*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
207*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
208*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
209*1c12ee1eSDan Willemsen			byte((v>>21)&0x7f|0x80),
210*1c12ee1eSDan Willemsen			byte(v>>28))
211*1c12ee1eSDan Willemsen	case v < 1<<42:
212*1c12ee1eSDan Willemsen		b = append(b,
213*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
214*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
215*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
216*1c12ee1eSDan Willemsen			byte((v>>21)&0x7f|0x80),
217*1c12ee1eSDan Willemsen			byte((v>>28)&0x7f|0x80),
218*1c12ee1eSDan Willemsen			byte(v>>35))
219*1c12ee1eSDan Willemsen	case v < 1<<49:
220*1c12ee1eSDan Willemsen		b = append(b,
221*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
222*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
223*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
224*1c12ee1eSDan Willemsen			byte((v>>21)&0x7f|0x80),
225*1c12ee1eSDan Willemsen			byte((v>>28)&0x7f|0x80),
226*1c12ee1eSDan Willemsen			byte((v>>35)&0x7f|0x80),
227*1c12ee1eSDan Willemsen			byte(v>>42))
228*1c12ee1eSDan Willemsen	case v < 1<<56:
229*1c12ee1eSDan Willemsen		b = append(b,
230*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
231*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
232*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
233*1c12ee1eSDan Willemsen			byte((v>>21)&0x7f|0x80),
234*1c12ee1eSDan Willemsen			byte((v>>28)&0x7f|0x80),
235*1c12ee1eSDan Willemsen			byte((v>>35)&0x7f|0x80),
236*1c12ee1eSDan Willemsen			byte((v>>42)&0x7f|0x80),
237*1c12ee1eSDan Willemsen			byte(v>>49))
238*1c12ee1eSDan Willemsen	case v < 1<<63:
239*1c12ee1eSDan Willemsen		b = append(b,
240*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
241*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
242*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
243*1c12ee1eSDan Willemsen			byte((v>>21)&0x7f|0x80),
244*1c12ee1eSDan Willemsen			byte((v>>28)&0x7f|0x80),
245*1c12ee1eSDan Willemsen			byte((v>>35)&0x7f|0x80),
246*1c12ee1eSDan Willemsen			byte((v>>42)&0x7f|0x80),
247*1c12ee1eSDan Willemsen			byte((v>>49)&0x7f|0x80),
248*1c12ee1eSDan Willemsen			byte(v>>56))
249*1c12ee1eSDan Willemsen	default:
250*1c12ee1eSDan Willemsen		b = append(b,
251*1c12ee1eSDan Willemsen			byte((v>>0)&0x7f|0x80),
252*1c12ee1eSDan Willemsen			byte((v>>7)&0x7f|0x80),
253*1c12ee1eSDan Willemsen			byte((v>>14)&0x7f|0x80),
254*1c12ee1eSDan Willemsen			byte((v>>21)&0x7f|0x80),
255*1c12ee1eSDan Willemsen			byte((v>>28)&0x7f|0x80),
256*1c12ee1eSDan Willemsen			byte((v>>35)&0x7f|0x80),
257*1c12ee1eSDan Willemsen			byte((v>>42)&0x7f|0x80),
258*1c12ee1eSDan Willemsen			byte((v>>49)&0x7f|0x80),
259*1c12ee1eSDan Willemsen			byte((v>>56)&0x7f|0x80),
260*1c12ee1eSDan Willemsen			1)
261*1c12ee1eSDan Willemsen	}
262*1c12ee1eSDan Willemsen	return b
263*1c12ee1eSDan Willemsen}
264*1c12ee1eSDan Willemsen
265*1c12ee1eSDan Willemsen// ConsumeVarint parses b as a varint-encoded uint64, reporting its length.
266*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
267*1c12ee1eSDan Willemsenfunc ConsumeVarint(b []byte) (v uint64, n int) {
268*1c12ee1eSDan Willemsen	var y uint64
269*1c12ee1eSDan Willemsen	if len(b) <= 0 {
270*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
271*1c12ee1eSDan Willemsen	}
272*1c12ee1eSDan Willemsen	v = uint64(b[0])
273*1c12ee1eSDan Willemsen	if v < 0x80 {
274*1c12ee1eSDan Willemsen		return v, 1
275*1c12ee1eSDan Willemsen	}
276*1c12ee1eSDan Willemsen	v -= 0x80
277*1c12ee1eSDan Willemsen
278*1c12ee1eSDan Willemsen	if len(b) <= 1 {
279*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
280*1c12ee1eSDan Willemsen	}
281*1c12ee1eSDan Willemsen	y = uint64(b[1])
282*1c12ee1eSDan Willemsen	v += y << 7
283*1c12ee1eSDan Willemsen	if y < 0x80 {
284*1c12ee1eSDan Willemsen		return v, 2
285*1c12ee1eSDan Willemsen	}
286*1c12ee1eSDan Willemsen	v -= 0x80 << 7
287*1c12ee1eSDan Willemsen
288*1c12ee1eSDan Willemsen	if len(b) <= 2 {
289*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
290*1c12ee1eSDan Willemsen	}
291*1c12ee1eSDan Willemsen	y = uint64(b[2])
292*1c12ee1eSDan Willemsen	v += y << 14
293*1c12ee1eSDan Willemsen	if y < 0x80 {
294*1c12ee1eSDan Willemsen		return v, 3
295*1c12ee1eSDan Willemsen	}
296*1c12ee1eSDan Willemsen	v -= 0x80 << 14
297*1c12ee1eSDan Willemsen
298*1c12ee1eSDan Willemsen	if len(b) <= 3 {
299*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
300*1c12ee1eSDan Willemsen	}
301*1c12ee1eSDan Willemsen	y = uint64(b[3])
302*1c12ee1eSDan Willemsen	v += y << 21
303*1c12ee1eSDan Willemsen	if y < 0x80 {
304*1c12ee1eSDan Willemsen		return v, 4
305*1c12ee1eSDan Willemsen	}
306*1c12ee1eSDan Willemsen	v -= 0x80 << 21
307*1c12ee1eSDan Willemsen
308*1c12ee1eSDan Willemsen	if len(b) <= 4 {
309*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
310*1c12ee1eSDan Willemsen	}
311*1c12ee1eSDan Willemsen	y = uint64(b[4])
312*1c12ee1eSDan Willemsen	v += y << 28
313*1c12ee1eSDan Willemsen	if y < 0x80 {
314*1c12ee1eSDan Willemsen		return v, 5
315*1c12ee1eSDan Willemsen	}
316*1c12ee1eSDan Willemsen	v -= 0x80 << 28
317*1c12ee1eSDan Willemsen
318*1c12ee1eSDan Willemsen	if len(b) <= 5 {
319*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
320*1c12ee1eSDan Willemsen	}
321*1c12ee1eSDan Willemsen	y = uint64(b[5])
322*1c12ee1eSDan Willemsen	v += y << 35
323*1c12ee1eSDan Willemsen	if y < 0x80 {
324*1c12ee1eSDan Willemsen		return v, 6
325*1c12ee1eSDan Willemsen	}
326*1c12ee1eSDan Willemsen	v -= 0x80 << 35
327*1c12ee1eSDan Willemsen
328*1c12ee1eSDan Willemsen	if len(b) <= 6 {
329*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
330*1c12ee1eSDan Willemsen	}
331*1c12ee1eSDan Willemsen	y = uint64(b[6])
332*1c12ee1eSDan Willemsen	v += y << 42
333*1c12ee1eSDan Willemsen	if y < 0x80 {
334*1c12ee1eSDan Willemsen		return v, 7
335*1c12ee1eSDan Willemsen	}
336*1c12ee1eSDan Willemsen	v -= 0x80 << 42
337*1c12ee1eSDan Willemsen
338*1c12ee1eSDan Willemsen	if len(b) <= 7 {
339*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
340*1c12ee1eSDan Willemsen	}
341*1c12ee1eSDan Willemsen	y = uint64(b[7])
342*1c12ee1eSDan Willemsen	v += y << 49
343*1c12ee1eSDan Willemsen	if y < 0x80 {
344*1c12ee1eSDan Willemsen		return v, 8
345*1c12ee1eSDan Willemsen	}
346*1c12ee1eSDan Willemsen	v -= 0x80 << 49
347*1c12ee1eSDan Willemsen
348*1c12ee1eSDan Willemsen	if len(b) <= 8 {
349*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
350*1c12ee1eSDan Willemsen	}
351*1c12ee1eSDan Willemsen	y = uint64(b[8])
352*1c12ee1eSDan Willemsen	v += y << 56
353*1c12ee1eSDan Willemsen	if y < 0x80 {
354*1c12ee1eSDan Willemsen		return v, 9
355*1c12ee1eSDan Willemsen	}
356*1c12ee1eSDan Willemsen	v -= 0x80 << 56
357*1c12ee1eSDan Willemsen
358*1c12ee1eSDan Willemsen	if len(b) <= 9 {
359*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
360*1c12ee1eSDan Willemsen	}
361*1c12ee1eSDan Willemsen	y = uint64(b[9])
362*1c12ee1eSDan Willemsen	v += y << 63
363*1c12ee1eSDan Willemsen	if y < 2 {
364*1c12ee1eSDan Willemsen		return v, 10
365*1c12ee1eSDan Willemsen	}
366*1c12ee1eSDan Willemsen	return 0, errCodeOverflow
367*1c12ee1eSDan Willemsen}
368*1c12ee1eSDan Willemsen
369*1c12ee1eSDan Willemsen// SizeVarint returns the encoded size of a varint.
370*1c12ee1eSDan Willemsen// The size is guaranteed to be within 1 and 10, inclusive.
371*1c12ee1eSDan Willemsenfunc SizeVarint(v uint64) int {
372*1c12ee1eSDan Willemsen	// This computes 1 + (bits.Len64(v)-1)/7.
373*1c12ee1eSDan Willemsen	// 9/64 is a good enough approximation of 1/7
374*1c12ee1eSDan Willemsen	return int(9*uint32(bits.Len64(v))+64) / 64
375*1c12ee1eSDan Willemsen}
376*1c12ee1eSDan Willemsen
377*1c12ee1eSDan Willemsen// AppendFixed32 appends v to b as a little-endian uint32.
378*1c12ee1eSDan Willemsenfunc AppendFixed32(b []byte, v uint32) []byte {
379*1c12ee1eSDan Willemsen	return append(b,
380*1c12ee1eSDan Willemsen		byte(v>>0),
381*1c12ee1eSDan Willemsen		byte(v>>8),
382*1c12ee1eSDan Willemsen		byte(v>>16),
383*1c12ee1eSDan Willemsen		byte(v>>24))
384*1c12ee1eSDan Willemsen}
385*1c12ee1eSDan Willemsen
386*1c12ee1eSDan Willemsen// ConsumeFixed32 parses b as a little-endian uint32, reporting its length.
387*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
388*1c12ee1eSDan Willemsenfunc ConsumeFixed32(b []byte) (v uint32, n int) {
389*1c12ee1eSDan Willemsen	if len(b) < 4 {
390*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
391*1c12ee1eSDan Willemsen	}
392*1c12ee1eSDan Willemsen	v = uint32(b[0])<<0 | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
393*1c12ee1eSDan Willemsen	return v, 4
394*1c12ee1eSDan Willemsen}
395*1c12ee1eSDan Willemsen
396*1c12ee1eSDan Willemsen// SizeFixed32 returns the encoded size of a fixed32; which is always 4.
397*1c12ee1eSDan Willemsenfunc SizeFixed32() int {
398*1c12ee1eSDan Willemsen	return 4
399*1c12ee1eSDan Willemsen}
400*1c12ee1eSDan Willemsen
401*1c12ee1eSDan Willemsen// AppendFixed64 appends v to b as a little-endian uint64.
402*1c12ee1eSDan Willemsenfunc AppendFixed64(b []byte, v uint64) []byte {
403*1c12ee1eSDan Willemsen	return append(b,
404*1c12ee1eSDan Willemsen		byte(v>>0),
405*1c12ee1eSDan Willemsen		byte(v>>8),
406*1c12ee1eSDan Willemsen		byte(v>>16),
407*1c12ee1eSDan Willemsen		byte(v>>24),
408*1c12ee1eSDan Willemsen		byte(v>>32),
409*1c12ee1eSDan Willemsen		byte(v>>40),
410*1c12ee1eSDan Willemsen		byte(v>>48),
411*1c12ee1eSDan Willemsen		byte(v>>56))
412*1c12ee1eSDan Willemsen}
413*1c12ee1eSDan Willemsen
414*1c12ee1eSDan Willemsen// ConsumeFixed64 parses b as a little-endian uint64, reporting its length.
415*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
416*1c12ee1eSDan Willemsenfunc ConsumeFixed64(b []byte) (v uint64, n int) {
417*1c12ee1eSDan Willemsen	if len(b) < 8 {
418*1c12ee1eSDan Willemsen		return 0, errCodeTruncated
419*1c12ee1eSDan Willemsen	}
420*1c12ee1eSDan Willemsen	v = uint64(b[0])<<0 | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
421*1c12ee1eSDan Willemsen	return v, 8
422*1c12ee1eSDan Willemsen}
423*1c12ee1eSDan Willemsen
424*1c12ee1eSDan Willemsen// SizeFixed64 returns the encoded size of a fixed64; which is always 8.
425*1c12ee1eSDan Willemsenfunc SizeFixed64() int {
426*1c12ee1eSDan Willemsen	return 8
427*1c12ee1eSDan Willemsen}
428*1c12ee1eSDan Willemsen
429*1c12ee1eSDan Willemsen// AppendBytes appends v to b as a length-prefixed bytes value.
430*1c12ee1eSDan Willemsenfunc AppendBytes(b []byte, v []byte) []byte {
431*1c12ee1eSDan Willemsen	return append(AppendVarint(b, uint64(len(v))), v...)
432*1c12ee1eSDan Willemsen}
433*1c12ee1eSDan Willemsen
434*1c12ee1eSDan Willemsen// ConsumeBytes parses b as a length-prefixed bytes value, reporting its length.
435*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
436*1c12ee1eSDan Willemsenfunc ConsumeBytes(b []byte) (v []byte, n int) {
437*1c12ee1eSDan Willemsen	m, n := ConsumeVarint(b)
438*1c12ee1eSDan Willemsen	if n < 0 {
439*1c12ee1eSDan Willemsen		return nil, n // forward error code
440*1c12ee1eSDan Willemsen	}
441*1c12ee1eSDan Willemsen	if m > uint64(len(b[n:])) {
442*1c12ee1eSDan Willemsen		return nil, errCodeTruncated
443*1c12ee1eSDan Willemsen	}
444*1c12ee1eSDan Willemsen	return b[n:][:m], n + int(m)
445*1c12ee1eSDan Willemsen}
446*1c12ee1eSDan Willemsen
447*1c12ee1eSDan Willemsen// SizeBytes returns the encoded size of a length-prefixed bytes value,
448*1c12ee1eSDan Willemsen// given only the length.
449*1c12ee1eSDan Willemsenfunc SizeBytes(n int) int {
450*1c12ee1eSDan Willemsen	return SizeVarint(uint64(n)) + n
451*1c12ee1eSDan Willemsen}
452*1c12ee1eSDan Willemsen
453*1c12ee1eSDan Willemsen// AppendString appends v to b as a length-prefixed bytes value.
454*1c12ee1eSDan Willemsenfunc AppendString(b []byte, v string) []byte {
455*1c12ee1eSDan Willemsen	return append(AppendVarint(b, uint64(len(v))), v...)
456*1c12ee1eSDan Willemsen}
457*1c12ee1eSDan Willemsen
458*1c12ee1eSDan Willemsen// ConsumeString parses b as a length-prefixed bytes value, reporting its length.
459*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
460*1c12ee1eSDan Willemsenfunc ConsumeString(b []byte) (v string, n int) {
461*1c12ee1eSDan Willemsen	bb, n := ConsumeBytes(b)
462*1c12ee1eSDan Willemsen	return string(bb), n
463*1c12ee1eSDan Willemsen}
464*1c12ee1eSDan Willemsen
465*1c12ee1eSDan Willemsen// AppendGroup appends v to b as group value, with a trailing end group marker.
466*1c12ee1eSDan Willemsen// The value v must not contain the end marker.
467*1c12ee1eSDan Willemsenfunc AppendGroup(b []byte, num Number, v []byte) []byte {
468*1c12ee1eSDan Willemsen	return AppendVarint(append(b, v...), EncodeTag(num, EndGroupType))
469*1c12ee1eSDan Willemsen}
470*1c12ee1eSDan Willemsen
471*1c12ee1eSDan Willemsen// ConsumeGroup parses b as a group value until the trailing end group marker,
472*1c12ee1eSDan Willemsen// and verifies that the end marker matches the provided num. The value v
473*1c12ee1eSDan Willemsen// does not contain the end marker, while the length does contain the end marker.
474*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError).
475*1c12ee1eSDan Willemsenfunc ConsumeGroup(num Number, b []byte) (v []byte, n int) {
476*1c12ee1eSDan Willemsen	n = ConsumeFieldValue(num, StartGroupType, b)
477*1c12ee1eSDan Willemsen	if n < 0 {
478*1c12ee1eSDan Willemsen		return nil, n // forward error code
479*1c12ee1eSDan Willemsen	}
480*1c12ee1eSDan Willemsen	b = b[:n]
481*1c12ee1eSDan Willemsen
482*1c12ee1eSDan Willemsen	// Truncate off end group marker, but need to handle denormalized varints.
483*1c12ee1eSDan Willemsen	// Assuming end marker is never 0 (which is always the case since
484*1c12ee1eSDan Willemsen	// EndGroupType is non-zero), we can truncate all trailing bytes where the
485*1c12ee1eSDan Willemsen	// lower 7 bits are all zero (implying that the varint is denormalized).
486*1c12ee1eSDan Willemsen	for len(b) > 0 && b[len(b)-1]&0x7f == 0 {
487*1c12ee1eSDan Willemsen		b = b[:len(b)-1]
488*1c12ee1eSDan Willemsen	}
489*1c12ee1eSDan Willemsen	b = b[:len(b)-SizeTag(num)]
490*1c12ee1eSDan Willemsen	return b, n
491*1c12ee1eSDan Willemsen}
492*1c12ee1eSDan Willemsen
493*1c12ee1eSDan Willemsen// SizeGroup returns the encoded size of a group, given only the length.
494*1c12ee1eSDan Willemsenfunc SizeGroup(num Number, n int) int {
495*1c12ee1eSDan Willemsen	return n + SizeTag(num)
496*1c12ee1eSDan Willemsen}
497*1c12ee1eSDan Willemsen
498*1c12ee1eSDan Willemsen// DecodeTag decodes the field Number and wire Type from its unified form.
499*1c12ee1eSDan Willemsen// The Number is -1 if the decoded field number overflows int32.
500*1c12ee1eSDan Willemsen// Other than overflow, this does not check for field number validity.
501*1c12ee1eSDan Willemsenfunc DecodeTag(x uint64) (Number, Type) {
502*1c12ee1eSDan Willemsen	// NOTE: MessageSet allows for larger field numbers than normal.
503*1c12ee1eSDan Willemsen	if x>>3 > uint64(math.MaxInt32) {
504*1c12ee1eSDan Willemsen		return -1, 0
505*1c12ee1eSDan Willemsen	}
506*1c12ee1eSDan Willemsen	return Number(x >> 3), Type(x & 7)
507*1c12ee1eSDan Willemsen}
508*1c12ee1eSDan Willemsen
509*1c12ee1eSDan Willemsen// EncodeTag encodes the field Number and wire Type into its unified form.
510*1c12ee1eSDan Willemsenfunc EncodeTag(num Number, typ Type) uint64 {
511*1c12ee1eSDan Willemsen	return uint64(num)<<3 | uint64(typ&7)
512*1c12ee1eSDan Willemsen}
513*1c12ee1eSDan Willemsen
514*1c12ee1eSDan Willemsen// DecodeZigZag decodes a zig-zag-encoded uint64 as an int64.
515*1c12ee1eSDan Willemsen//
516*1c12ee1eSDan Willemsen//	Input:  {…,  5,  3,  1,  0,  2,  4,  6, …}
517*1c12ee1eSDan Willemsen//	Output: {…, -3, -2, -1,  0, +1, +2, +3, …}
518*1c12ee1eSDan Willemsenfunc DecodeZigZag(x uint64) int64 {
519*1c12ee1eSDan Willemsen	return int64(x>>1) ^ int64(x)<<63>>63
520*1c12ee1eSDan Willemsen}
521*1c12ee1eSDan Willemsen
522*1c12ee1eSDan Willemsen// EncodeZigZag encodes an int64 as a zig-zag-encoded uint64.
523*1c12ee1eSDan Willemsen//
524*1c12ee1eSDan Willemsen//	Input:  {…, -3, -2, -1,  0, +1, +2, +3, …}
525*1c12ee1eSDan Willemsen//	Output: {…,  5,  3,  1,  0,  2,  4,  6, …}
526*1c12ee1eSDan Willemsenfunc EncodeZigZag(x int64) uint64 {
527*1c12ee1eSDan Willemsen	return uint64(x<<1) ^ uint64(x>>63)
528*1c12ee1eSDan Willemsen}
529*1c12ee1eSDan Willemsen
530*1c12ee1eSDan Willemsen// DecodeBool decodes a uint64 as a bool.
531*1c12ee1eSDan Willemsen//
532*1c12ee1eSDan Willemsen//	Input:  {    0,    1,    2, …}
533*1c12ee1eSDan Willemsen//	Output: {false, true, true, …}
534*1c12ee1eSDan Willemsenfunc DecodeBool(x uint64) bool {
535*1c12ee1eSDan Willemsen	return x != 0
536*1c12ee1eSDan Willemsen}
537*1c12ee1eSDan Willemsen
538*1c12ee1eSDan Willemsen// EncodeBool encodes a bool as a uint64.
539*1c12ee1eSDan Willemsen//
540*1c12ee1eSDan Willemsen//	Input:  {false, true}
541*1c12ee1eSDan Willemsen//	Output: {    0,    1}
542*1c12ee1eSDan Willemsenfunc EncodeBool(x bool) uint64 {
543*1c12ee1eSDan Willemsen	if x {
544*1c12ee1eSDan Willemsen		return 1
545*1c12ee1eSDan Willemsen	}
546*1c12ee1eSDan Willemsen	return 0
547*1c12ee1eSDan Willemsen}
548