Documentation
¶
Overview ¶
Package wire implements the foundational wire format encoding and decoding primitives for a Protocol Buffers library. It provides varint (base-128 LEB128), ZigZag signed integer encoding, and fixed-width 32-bit/64-bit encoding and decoding with zero-allocation append-style APIs.
All encoding functions follow the append pattern: they take a byte slice, append encoded bytes to it, and return the extended slice. All decoding functions follow the consume pattern: they read from the front of a byte slice and return the decoded value along with the number of bytes consumed. A negative bytes-consumed value signals an error; use ParseError to convert it to a sentinel error.
This package has zero external dependencies and does not import encoding/binary. All byte manipulation is performed directly.
Index ¶
- Constants
- Variables
- func AppendBytes(b []byte, data []byte) []byte
- func AppendFixed32(b []byte, v uint32) []byte
- func AppendFixed64(b []byte, v uint64) []byte
- func AppendFloat32(b []byte, v float32) []byte
- func AppendFloat64(b []byte, v float64) []byte
- func AppendString(b []byte, s string) []byte
- func AppendTag(b []byte, fieldNumber uint32, wireType WireType) []byte
- func AppendVarint(b []byte, v uint64) []byte
- func ConsumeBytes(b []byte) (data []byte, bytesConsumed int)
- func ConsumeField(wireType WireType, b []byte) int
- func ConsumeFixed32(b []byte) (uint32, int)
- func ConsumeFixed64(b []byte) (uint64, int)
- func ConsumeFloat32(b []byte) (float32, int)
- func ConsumeFloat64(b []byte) (float64, int)
- func ConsumeString(b []byte) (string, int)
- func ConsumeVarint(b []byte) (value uint64, bytesConsumed int)
- func DecodeZigZag32(v uint32) int32
- func DecodeZigZag64(v uint64) int64
- func EncodeTag(fieldNumber uint32, wireType WireType) uint64
- func EncodeZigZag32(v int32) uint32
- func EncodeZigZag64(v int64) uint64
- func ParseError(n int) error
- func SizeBytes(dataLen int) int
- func SizeTag(fieldNumber uint32) int
- func SizeVarint(v uint64) int
- type BytesCodec
- type Codec
- func (c *Codec) AppendBytes(b []byte, data []byte) []byte
- func (c *Codec) AppendFixed32(b []byte, v uint32) []byte
- func (c *Codec) AppendFixed64(b []byte, v uint64) []byte
- func (c *Codec) AppendFloat32(b []byte, v float32) []byte
- func (c *Codec) AppendFloat64(b []byte, v float64) []byte
- func (c *Codec) AppendString(b []byte, s string) []byte
- func (c *Codec) AppendTag(b []byte, fieldNumber uint32, wireType WireType) []byte
- func (c *Codec) AppendVarint(b []byte, v uint64) []byte
- func (c *Codec) ConsumeBytes(b []byte) ([]byte, int)
- func (c *Codec) ConsumeFixed32(b []byte) (uint32, int)
- func (c *Codec) ConsumeFixed64(b []byte) (uint64, int)
- func (c *Codec) ConsumeFloat32(b []byte) (float32, int)
- func (c *Codec) ConsumeFloat64(b []byte) (float64, int)
- func (c *Codec) ConsumeString(b []byte) (string, int)
- func (c *Codec) ConsumeTag(b []byte) (uint32, WireType, int)
- func (c *Codec) ConsumeVarint(b []byte) (uint64, int)
- func (c *Codec) DecodeTag(tag uint64) (uint32, WireType)
- func (c *Codec) DecodeZigZag32(v uint32) int32
- func (c *Codec) DecodeZigZag64(v uint64) int64
- func (c *Codec) EncodeTag(fieldNumber uint32, wireType WireType) uint64
- func (c *Codec) EncodeZigZag32(v int32) uint32
- func (c *Codec) EncodeZigZag64(v int64) uint64
- func (c *Codec) SizeBytes(dataLen int) int
- func (c *Codec) SizeTag(fieldNumber uint32) int
- func (c *Codec) SizeVarint(v uint64) int
- type FixedCodec
- type TagCodec
- type VarintCodec
- type WireType
- type ZigZagCodec
Constants ¶
const MaxFieldNumber uint32 = 1<<29 - 1
MaxFieldNumber is the largest valid protocol buffer field number (2^29 - 1).
const MaxMessageSize = 2*1024*1024*1024 - 1
MaxMessageSize is the maximum allowed message size in bytes, equal to the maximum value of a signed 32-bit integer (2 GiB - 1).
const MaxVarintLen32 = 5
MaxVarintLen32 is the maximum number of bytes required to encode a uint32 value as a base-128 varint.
const MaxVarintLen64 = 10
MaxVarintLen64 is the maximum number of bytes required to encode a uint64 value as a base-128 varint.
const MinFieldNumber uint32 = 1
MinFieldNumber is the smallest valid protocol buffer field number.
Variables ¶
var ErrGroupDepthExceeded = errors.New("wire: group nesting depth exceeded")
ErrGroupDepthExceeded indicates that group nesting depth has exceeded the maximum allowed limit during field skipping. It is returned by ParseError when a Consume function signals excessive group nesting via errCodeGroupDepthExceeded.
var ErrInvalidFieldNumber = errors.New("wire: invalid field number")
ErrInvalidFieldNumber indicates that a decoded field number is outside the valid range (1 to 536,870,911). It is returned by ParseError when a Consume function signals an invalid field number via errCodeInvalidFieldNumber.
var ErrInvalidWireType = errors.New("wire: invalid wire type")
ErrInvalidWireType indicates that a decoded wire type is outside the valid range (0 to 5). It is returned by ParseError when a Consume function signals an invalid wire type via errCodeInvalidWireType.
var ErrMessageTooLarge = errors.New("wire: message size exceeds 2 GiB limit")
ErrMessageTooLarge indicates that a length-delimited field exceeds the 2 GiB maximum message size. It is returned by ParseError when a Consume function signals a message size violation via errCodeMessageTooLarge.
var ErrOverflow = errors.New("wire: varint overflow")
ErrOverflow indicates that a varint value overflows a uint64. It is returned by ParseError when a Consume function signals overflow via a negative bytes-consumed value of errCodeOverflow.
var ErrTruncated = errors.New("wire: unexpected end of input")
ErrTruncated indicates that the input ended before a complete value could be decoded. It is returned by ParseError when a Consume function signals a truncated input via a negative bytes-consumed value of errCodeTruncated.
Functions ¶
func AppendBytes ¶
AppendBytes appends a length-delimited byte field to b and returns the extended slice. It first appends the length of data as a varint prefix, then appends the raw data bytes. This function performs zero allocations; it only appends to the caller-provided slice.
func AppendFixed32 ¶
AppendFixed32 appends the little-endian encoding of v to b and returns the extended slice. It uses direct byte manipulation without importing encoding/binary.
func AppendFixed64 ¶
AppendFixed64 appends the little-endian encoding of v to b and returns the extended slice. It uses direct byte manipulation without importing encoding/binary.
func AppendFloat32 ¶
AppendFloat32 appends the little-endian IEEE 754 encoding of v to b and returns the extended slice. It converts the float32 to its bit representation via math.Float32bits and delegates to AppendFixed32.
func AppendFloat64 ¶
AppendFloat64 appends the little-endian IEEE 754 encoding of v to b and returns the extended slice. It converts the float64 to its bit representation via math.Float64bits and delegates to AppendFixed64.
func AppendString ¶
AppendString appends a length-delimited string field to b and returns the extended slice. It uses append(b, s...) to avoid an intermediate []byte conversion allocation.
func AppendTag ¶
AppendTag encodes a field tag as a varint and appends it to b, returning the extended slice. It delegates to EncodeTag for the numeric tag value and AppendVarint for the byte encoding. No validation is performed.
func AppendVarint ¶
AppendVarint appends the base-128 varint encoding of v to b and returns the extended slice. Each byte uses bits 0-6 for data and bit 7 (MSB) as a continuation flag. The byte order is little-endian, with the least significant 7-bit group emitted first. This function performs zero allocations; it only appends to the caller-provided slice.
func ConsumeBytes ¶
ConsumeBytes reads a length-delimited byte field from the front of b. It returns the data as a sub-slice of the input (zero-copy, no allocation) and the total number of bytes consumed (varint prefix + data).
If the input is malformed, bytesConsumed is a negative error code:
- errCodeTruncated / errCodeOverflow: propagated from ConsumeVarint
- errCodeMessageTooLarge: decoded length exceeds MaxMessageSize
- errCodeTruncated: decoded length exceeds remaining bytes
Use ParseError to convert a negative bytesConsumed into a sentinel error.
func ConsumeField ¶
ConsumeField returns the number of bytes consumed to skip over one field value of the given wire type, without decoding the actual value. The byte slice b must contain the field value only (not the tag). If the data is malformed or insufficient, the return value is a negative error code.
Use ParseError to convert a negative return value into a sentinel error.
func ConsumeFixed32 ¶
ConsumeFixed32 reads a little-endian encoded uint32 from the front of b. It returns the decoded value and the number of bytes consumed (4). If len(b) < 4, it returns (0, errCodeTruncated) where errCodeTruncated is a negative value; use ParseError to convert it to the ErrTruncated sentinel.
func ConsumeFixed64 ¶
ConsumeFixed64 reads a little-endian encoded uint64 from the front of b. It returns the decoded value and the number of bytes consumed (8). If len(b) < 8, it returns (0, errCodeTruncated) where errCodeTruncated is a negative value; use ParseError to convert it to the ErrTruncated sentinel.
func ConsumeFloat32 ¶
ConsumeFloat32 reads a little-endian IEEE 754 encoded float32 from the front of b. It returns the decoded value and the number of bytes consumed (4). If len(b) < 4, it returns (0, errCodeTruncated) where errCodeTruncated is a negative value; use ParseError to convert it to the ErrTruncated sentinel.
func ConsumeFloat64 ¶
ConsumeFloat64 reads a little-endian IEEE 754 encoded float64 from the front of b. It returns the decoded value and the number of bytes consumed (8). If len(b) < 8, it returns (0, errCodeTruncated) where errCodeTruncated is a negative value; use ParseError to convert it to the ErrTruncated sentinel.
func ConsumeString ¶
ConsumeString reads a length-delimited string field from the front of b. It returns the decoded string and the total number of bytes consumed. The string conversion from the sub-slice is the only allocation performed.
If the input is malformed, bytesConsumed is a negative error code; see ConsumeBytes for the possible error codes.
func ConsumeVarint ¶
ConsumeVarint reads a base-128 varint from the front of b. It returns the decoded uint64 value and the number of bytes consumed.
If the input is malformed, bytesConsumed is a negative error code:
- errCodeTruncated (-1): the input ends before a byte with MSB=0 is found
- errCodeOverflow (-2): more than 10 continuation bytes, or the 10th byte exceeds 0x01, which would overflow a uint64
Use ParseError to convert a negative bytesConsumed into a sentinel error.
func DecodeZigZag32 ¶
DecodeZigZag32 decodes a ZigZag-encoded uint32 back to the original signed int32 value. It reverses the mapping performed by EncodeZigZag32.
func DecodeZigZag64 ¶
DecodeZigZag64 decodes a ZigZag-encoded uint64 back to the original signed int64 value. It reverses the mapping performed by EncodeZigZag64.
func EncodeTag ¶
EncodeTag encodes a field number and wire type into a single tag value. The tag is formed by shifting the field number left by 3 bits and OR-ing in the wire type. This function performs no validation; it is a low-level hot-path helper that trusts the caller to supply valid inputs.
func EncodeZigZag32 ¶
EncodeZigZag32 encodes a signed int32 using ZigZag encoding, mapping small absolute values to small unsigned values: 0->0, -1->1, 1->2, -2->3, 2->4. The encoding uses pure bit manipulation with no branching or allocations.
func EncodeZigZag64 ¶
EncodeZigZag64 encodes a signed int64 using ZigZag encoding, mapping small absolute values to small unsigned values: 0->0, -1->1, 1->2, -2->3, 2->4. The encoding uses pure bit manipulation with no branching or allocations.
func ParseError ¶
ParseError converts a negative bytes-consumed value returned by a Consume function into the corresponding sentinel error. If n is non-negative, ParseError returns nil, indicating no error occurred.
func SizeBytes ¶
SizeBytes returns the number of bytes required to encode a length-delimited field whose data payload is dataLen bytes long. The result includes both the varint-encoded length prefix and the data itself.
func SizeTag ¶
SizeTag returns the number of bytes required to encode the tag for the given field number as a varint. The wire type bits do not affect the varint length, so a zero wire type is used for the computation.
func SizeVarint ¶
SizeVarint returns the number of bytes required to encode v as a base-128 varint, without performing the encoding. It uses a branchless computation based on the bit length of v.
Types ¶
type BytesCodec ¶
type BytesCodec interface {
AppendBytes([]byte, []byte) []byte
ConsumeBytes([]byte) ([]byte, int)
SizeBytes(int) int
AppendString([]byte, string) []byte
ConsumeString([]byte) (string, int)
}
BytesCodec is the interface for length-delimited byte and string field encoding and decoding. It enables dependency inversion so that higher-level packages can accept a bytes codec without coupling to this package's concrete functions.
type Codec ¶
type Codec struct{}
Codec is a stateless struct that implements the VarintCodec, ZigZagCodec, FixedCodec, TagCodec, and BytesCodec interfaces. Each method delegates to the corresponding package-level function. Codec exists so that higher-level packages can depend on interfaces rather than concrete functions, enabling dependency inversion and easier testing.
func NewCodec ¶
func NewCodec() *Codec
NewCodec returns a pointer to a new Codec instance. The returned value satisfies VarintCodec, ZigZagCodec, FixedCodec, TagCodec, and BytesCodec.
func (*Codec) AppendBytes ¶
AppendBytes delegates to the package-level AppendBytes function.
func (*Codec) AppendFixed32 ¶
AppendFixed32 delegates to the package-level AppendFixed32 function.
func (*Codec) AppendFixed64 ¶
AppendFixed64 delegates to the package-level AppendFixed64 function.
func (*Codec) AppendFloat32 ¶
AppendFloat32 delegates to the package-level AppendFloat32 function.
func (*Codec) AppendFloat64 ¶
AppendFloat64 delegates to the package-level AppendFloat64 function.
func (*Codec) AppendString ¶
AppendString delegates to the package-level AppendString function.
func (*Codec) AppendVarint ¶
AppendVarint delegates to the package-level AppendVarint function.
func (*Codec) ConsumeBytes ¶
ConsumeBytes delegates to the package-level ConsumeBytes function.
func (*Codec) ConsumeFixed32 ¶
ConsumeFixed32 delegates to the package-level ConsumeFixed32 function.
func (*Codec) ConsumeFixed64 ¶
ConsumeFixed64 delegates to the package-level ConsumeFixed64 function.
func (*Codec) ConsumeFloat32 ¶
ConsumeFloat32 delegates to the package-level ConsumeFloat32 function.
func (*Codec) ConsumeFloat64 ¶
ConsumeFloat64 delegates to the package-level ConsumeFloat64 function.
func (*Codec) ConsumeString ¶
ConsumeString delegates to the package-level ConsumeString function.
func (*Codec) ConsumeTag ¶
ConsumeTag delegates to the package-level ConsumeTag function.
func (*Codec) ConsumeVarint ¶
ConsumeVarint delegates to the package-level ConsumeVarint function.
func (*Codec) DecodeZigZag32 ¶
DecodeZigZag32 delegates to the package-level DecodeZigZag32 function.
func (*Codec) DecodeZigZag64 ¶
DecodeZigZag64 delegates to the package-level DecodeZigZag64 function.
func (*Codec) EncodeZigZag32 ¶
EncodeZigZag32 delegates to the package-level EncodeZigZag32 function.
func (*Codec) EncodeZigZag64 ¶
EncodeZigZag64 delegates to the package-level EncodeZigZag64 function.
func (*Codec) SizeVarint ¶
SizeVarint delegates to the package-level SizeVarint function.
type FixedCodec ¶
type FixedCodec interface {
AppendFixed32([]byte, uint32) []byte
ConsumeFixed32([]byte) (uint32, int)
AppendFixed64([]byte, uint64) []byte
ConsumeFixed64([]byte) (uint64, int)
AppendFloat32([]byte, float32) []byte
ConsumeFloat32([]byte) (float32, int)
AppendFloat64([]byte, float64) []byte
ConsumeFloat64([]byte) (float64, int)
}
FixedCodec is the interface for fixed-width 32-bit and 64-bit encoding and decoding, including IEEE 754 float variants. It enables dependency inversion so that higher-level packages can accept a fixed-width codec without coupling to this package's concrete functions.
ISP note: FixedCodec has 8 methods (4 types x append/consume pairs). Splitting by width (32-bit vs. 64-bit) or by type (integer vs. float) was evaluated, but all consumers that use fixed-width encoding need the full set because protobuf messages mix fixed32, fixed64, float, and double fields freely. No consumer uses only a subset. This is documented as an accepted exception to the 5-method guideline.
type TagCodec ¶
type TagCodec interface {
EncodeTag(uint32, WireType) uint64
DecodeTag(uint64) (uint32, WireType)
AppendTag([]byte, uint32, WireType) []byte
ConsumeTag([]byte) (uint32, WireType, int)
SizeTag(uint32) int
}
TagCodec is the interface for field tag encoding, decoding, and size computation. It enables dependency inversion so that higher-level packages can accept a tag codec without coupling to this package's concrete functions.
type VarintCodec ¶
type VarintCodec interface {
AppendVarint([]byte, uint64) []byte
ConsumeVarint([]byte) (uint64, int)
SizeVarint(uint64) int
}
VarintCodec is the interface for base-128 varint encoding, decoding, and size computation. It enables dependency inversion so that higher-level packages can accept a varint codec without depending on this package's concrete functions directly.
type WireType ¶
type WireType int8
WireType represents one of the six protocol buffer wire format types. It is a named type over int8 to provide type safety and prevent silent confusion with raw integers.
const ( // WireVarint identifies the base-128 varint encoding (wire type 0). WireVarint WireType = 0 // WireFixed64 identifies the fixed 64-bit encoding (wire type 1). WireFixed64 WireType = 1 // WireBytes identifies the length-delimited encoding (wire type 2). WireBytes WireType = 2 // WireStartGroup identifies the start-group marker (wire type 3). // Groups are deprecated in proto3 but must still be understood at the // wire level for forward compatibility. WireStartGroup WireType = 3 // WireEndGroup identifies the end-group marker (wire type 4). WireEndGroup WireType = 4 // WireFixed32 identifies the fixed 32-bit encoding (wire type 5). WireFixed32 WireType = 5 )
Wire type constants for the six protocol buffer wire format types.
func ConsumeTag ¶
ConsumeTag reads a field tag varint from the front of b and returns the decoded field number, wire type, and number of bytes consumed. If the input is malformed or the decoded values are outside their valid ranges, bytesConsumed is a negative error code:
- errCodeTruncated / errCodeOverflow: propagated from ConsumeVarint
- errCodeInvalidFieldNumber: field number is 0 or exceeds MaxFieldNumber
- errCodeInvalidWireType: wire type is outside the range 0-5
Use ParseError to convert a negative bytesConsumed into a sentinel error.
func DecodeTag ¶
DecodeTag decodes a raw tag value into its field number and wire type components. The field number is extracted from bits 3+ and the wire type from the lowest 3 bits. This function performs no validation; it is a low-level hot-path helper that trusts the caller.
type ZigZagCodec ¶
type ZigZagCodec interface {
EncodeZigZag64(int64) uint64
DecodeZigZag64(uint64) int64
EncodeZigZag32(int32) uint32
DecodeZigZag32(uint32) int32
}
ZigZagCodec is the interface for ZigZag signed integer encoding and decoding. It enables dependency inversion so that higher-level packages can accept a ZigZag codec without coupling to this package's concrete functions.