// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package protowire parses and formats the raw wire encoding. // See https://developers.google.com/protocol-buffers/docs/encoding. // // For marshaling and unmarshaling entire protobuf messages, // use the "google.golang.org/protobuf/proto" package instead.
package protowire import ( ) // Number represents the field number. type Number int32 const ( MinValidNumber Number = 1 FirstReservedNumber Number = 19000 LastReservedNumber Number = 19999 MaxValidNumber Number = 1<<29 - 1 DefaultRecursionLimit = 10000 ) // IsValid reports whether the field number is semantically valid. // // Note that while numbers within the reserved range are semantically invalid, // they are syntactically valid in the wire format. // Implementations may treat records with reserved field numbers as unknown. func ( Number) () bool { return MinValidNumber <= && < FirstReservedNumber || LastReservedNumber < && <= MaxValidNumber } // Type represents the wire type. type Type int8 const ( VarintType Type = 0 Fixed32Type Type = 5 Fixed64Type Type = 1 BytesType Type = 2 StartGroupType Type = 3 EndGroupType Type = 4 ) const ( _ = -iota errCodeTruncated errCodeFieldNumber errCodeOverflow errCodeReserved errCodeEndGroup errCodeRecursionDepth ) var ( errFieldNumber = errors.New("invalid field number") errOverflow = errors.New("variable length integer overflow") errReserved = errors.New("cannot parse reserved wire type") errEndGroup = errors.New("mismatching end group marker") errParse = errors.New("parse error") ) // ParseError converts an error code into an error value. // This returns nil if n is a non-negative number. func ( int) error { if >= 0 { return nil } switch { case errCodeTruncated: return io.ErrUnexpectedEOF case errCodeFieldNumber: return errFieldNumber case errCodeOverflow: return errOverflow case errCodeReserved: return errReserved case errCodeEndGroup: return errEndGroup default: return errParse } } // ConsumeField parses an entire field record (both tag and value) and returns // the field number, the wire type, and the total length. // This returns a negative length upon an error (see ParseError). // // The total length includes the tag header and the end group marker (if the // field is a group). func ( []byte) (Number, Type, int) { , , := ConsumeTag() if < 0 { return 0, 0, // forward error code } := ConsumeFieldValue(, , [:]) if < 0 { return 0, 0, // forward error code } return , , + } // ConsumeFieldValue parses a field value and returns its length. // This assumes that the field Number and wire Type have already been parsed. // This returns a negative length upon an error (see ParseError). // // When parsing a group, the length includes the end group marker and // the end group is verified to match the starting field number. func ( Number, Type, []byte) ( int) { return consumeFieldValueD(, , , DefaultRecursionLimit) } func ( Number, Type, []byte, int) ( int) { switch { case VarintType: _, = ConsumeVarint() return case Fixed32Type: _, = ConsumeFixed32() return case Fixed64Type: _, = ConsumeFixed64() return case BytesType: _, = ConsumeBytes() return case StartGroupType: if < 0 { return errCodeRecursionDepth } := len() for { , , := ConsumeTag() if < 0 { return // forward error code } = [:] if == EndGroupType { if != { return errCodeEndGroup } return - len() } = (, , , -1) if < 0 { return // forward error code } = [:] } case EndGroupType: return errCodeEndGroup default: return errCodeReserved } } // AppendTag encodes num and typ as a varint-encoded tag and appends it to b. func ( []byte, Number, Type) []byte { return AppendVarint(, EncodeTag(, )) } // ConsumeTag parses b as a varint-encoded tag, reporting its length. // This returns a negative length upon an error (see ParseError). func ( []byte) (Number, Type, int) { , := ConsumeVarint() if < 0 { return 0, 0, // forward error code } , := DecodeTag() if < MinValidNumber { return 0, 0, errCodeFieldNumber } return , , } func ( Number) int { return SizeVarint(EncodeTag(, 0)) // wire type has no effect on size } // AppendVarint appends v to b as a varint-encoded uint64. func ( []byte, uint64) []byte { switch { case < 1<<7: = append(, byte()) case < 1<<14: = append(, byte((>>0)&0x7f|0x80), byte(>>7)) case < 1<<21: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte(>>14)) case < 1<<28: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte(>>21)) case < 1<<35: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte((>>21)&0x7f|0x80), byte(>>28)) case < 1<<42: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte((>>21)&0x7f|0x80), byte((>>28)&0x7f|0x80), byte(>>35)) case < 1<<49: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte((>>21)&0x7f|0x80), byte((>>28)&0x7f|0x80), byte((>>35)&0x7f|0x80), byte(>>42)) case < 1<<56: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte((>>21)&0x7f|0x80), byte((>>28)&0x7f|0x80), byte((>>35)&0x7f|0x80), byte((>>42)&0x7f|0x80), byte(>>49)) case < 1<<63: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte((>>21)&0x7f|0x80), byte((>>28)&0x7f|0x80), byte((>>35)&0x7f|0x80), byte((>>42)&0x7f|0x80), byte((>>49)&0x7f|0x80), byte(>>56)) default: = append(, byte((>>0)&0x7f|0x80), byte((>>7)&0x7f|0x80), byte((>>14)&0x7f|0x80), byte((>>21)&0x7f|0x80), byte((>>28)&0x7f|0x80), byte((>>35)&0x7f|0x80), byte((>>42)&0x7f|0x80), byte((>>49)&0x7f|0x80), byte((>>56)&0x7f|0x80), 1) } return } // ConsumeVarint parses b as a varint-encoded uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ( []byte) ( uint64, int) { var uint64 if len() <= 0 { return 0, errCodeTruncated } = uint64([0]) if < 0x80 { return , 1 } -= 0x80 if len() <= 1 { return 0, errCodeTruncated } = uint64([1]) += << 7 if < 0x80 { return , 2 } -= 0x80 << 7 if len() <= 2 { return 0, errCodeTruncated } = uint64([2]) += << 14 if < 0x80 { return , 3 } -= 0x80 << 14 if len() <= 3 { return 0, errCodeTruncated } = uint64([3]) += << 21 if < 0x80 { return , 4 } -= 0x80 << 21 if len() <= 4 { return 0, errCodeTruncated } = uint64([4]) += << 28 if < 0x80 { return , 5 } -= 0x80 << 28 if len() <= 5 { return 0, errCodeTruncated } = uint64([5]) += << 35 if < 0x80 { return , 6 } -= 0x80 << 35 if len() <= 6 { return 0, errCodeTruncated } = uint64([6]) += << 42 if < 0x80 { return , 7 } -= 0x80 << 42 if len() <= 7 { return 0, errCodeTruncated } = uint64([7]) += << 49 if < 0x80 { return , 8 } -= 0x80 << 49 if len() <= 8 { return 0, errCodeTruncated } = uint64([8]) += << 56 if < 0x80 { return , 9 } -= 0x80 << 56 if len() <= 9 { return 0, errCodeTruncated } = uint64([9]) += << 63 if < 2 { return , 10 } return 0, errCodeOverflow } // SizeVarint returns the encoded size of a varint. // The size is guaranteed to be within 1 and 10, inclusive. func ( uint64) int { // This computes 1 + (bits.Len64(v)-1)/7. // 9/64 is a good enough approximation of 1/7 return int(9*uint32(bits.Len64())+64) / 64 } // AppendFixed32 appends v to b as a little-endian uint32. func ( []byte, uint32) []byte { return append(, byte(>>0), byte(>>8), byte(>>16), byte(>>24)) } // ConsumeFixed32 parses b as a little-endian uint32, reporting its length. // This returns a negative length upon an error (see ParseError). func ( []byte) ( uint32, int) { if len() < 4 { return 0, errCodeTruncated } = uint32([0])<<0 | uint32([1])<<8 | uint32([2])<<16 | uint32([3])<<24 return , 4 } // SizeFixed32 returns the encoded size of a fixed32; which is always 4. func () int { return 4 } // AppendFixed64 appends v to b as a little-endian uint64. func ( []byte, uint64) []byte { return append(, byte(>>0), byte(>>8), byte(>>16), byte(>>24), byte(>>32), byte(>>40), byte(>>48), byte(>>56)) } // ConsumeFixed64 parses b as a little-endian uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ( []byte) ( uint64, int) { if len() < 8 { return 0, errCodeTruncated } = uint64([0])<<0 | uint64([1])<<8 | uint64([2])<<16 | uint64([3])<<24 | uint64([4])<<32 | uint64([5])<<40 | uint64([6])<<48 | uint64([7])<<56 return , 8 } // SizeFixed64 returns the encoded size of a fixed64; which is always 8. func () int { return 8 } // AppendBytes appends v to b as a length-prefixed bytes value. func ( []byte, []byte) []byte { return append(AppendVarint(, uint64(len())), ...) } // ConsumeBytes parses b as a length-prefixed bytes value, reporting its length. // This returns a negative length upon an error (see ParseError). func ( []byte) ( []byte, int) { , := ConsumeVarint() if < 0 { return nil, // forward error code } if > uint64(len([:])) { return nil, errCodeTruncated } return [:][:], + int() } // SizeBytes returns the encoded size of a length-prefixed bytes value, // given only the length. func ( int) int { return SizeVarint(uint64()) + } // AppendString appends v to b as a length-prefixed bytes value. func ( []byte, string) []byte { return append(AppendVarint(, uint64(len())), ...) } // ConsumeString parses b as a length-prefixed bytes value, reporting its length. // This returns a negative length upon an error (see ParseError). func ( []byte) ( string, int) { , := ConsumeBytes() return string(), } // AppendGroup appends v to b as group value, with a trailing end group marker. // The value v must not contain the end marker. func ( []byte, Number, []byte) []byte { return AppendVarint(append(, ...), EncodeTag(, EndGroupType)) } // ConsumeGroup parses b as a group value until the trailing end group marker, // and verifies that the end marker matches the provided num. The value v // does not contain the end marker, while the length does contain the end marker. // This returns a negative length upon an error (see ParseError). func ( Number, []byte) ( []byte, int) { = ConsumeFieldValue(, StartGroupType, ) if < 0 { return nil, // forward error code } = [:] // Truncate off end group marker, but need to handle denormalized varints. // Assuming end marker is never 0 (which is always the case since // EndGroupType is non-zero), we can truncate all trailing bytes where the // lower 7 bits are all zero (implying that the varint is denormalized). for len() > 0 && [len()-1]&0x7f == 0 { = [:len()-1] } = [:len()-SizeTag()] return , } // SizeGroup returns the encoded size of a group, given only the length. func ( Number, int) int { return + SizeTag() } // DecodeTag decodes the field Number and wire Type from its unified form. // The Number is -1 if the decoded field number overflows int32. // Other than overflow, this does not check for field number validity. func ( uint64) (Number, Type) { // NOTE: MessageSet allows for larger field numbers than normal. if >>3 > uint64(math.MaxInt32) { return -1, 0 } return Number( >> 3), Type( & 7) } // EncodeTag encodes the field Number and wire Type into its unified form. func ( Number, Type) uint64 { return uint64()<<3 | uint64(&7) } // DecodeZigZag decodes a zig-zag-encoded uint64 as an int64. // // Input: {…, 5, 3, 1, 0, 2, 4, 6, …} // Output: {…, -3, -2, -1, 0, +1, +2, +3, …} func ( uint64) int64 { return int64(>>1) ^ int64()<<63>>63 } // EncodeZigZag encodes an int64 as a zig-zag-encoded uint64. // // Input: {…, -3, -2, -1, 0, +1, +2, +3, …} // Output: {…, 5, 3, 1, 0, 2, 4, 6, …} func ( int64) uint64 { return uint64(<<1) ^ uint64(>>63) } // DecodeBool decodes a uint64 as a bool. // // Input: { 0, 1, 2, …} // Output: {false, true, true, …} func ( uint64) bool { return != 0 } // EncodeBool encodes a bool as a uint64. // // Input: {false, true} // Output: { 0, 1} func ( bool) uint64 { if { return 1 } return 0 }