wire

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 4 Imported by: 0

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

View Source
const MaxFieldNumber uint32 = 1<<29 - 1

MaxFieldNumber is the largest valid protocol buffer field number (2^29 - 1).

View Source
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).

View Source
const MaxVarintLen32 = 5

MaxVarintLen32 is the maximum number of bytes required to encode a uint32 value as a base-128 varint.

View Source
const MaxVarintLen64 = 10

MaxVarintLen64 is the maximum number of bytes required to encode a uint64 value as a base-128 varint.

View Source
const MinFieldNumber uint32 = 1

MinFieldNumber is the smallest valid protocol buffer field number.

Variables

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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

func AppendBytes(b []byte, data []byte) []byte

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

func AppendFixed32(b []byte, v uint32) []byte

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

func AppendFixed64(b []byte, v uint64) []byte

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

func AppendFloat32(b []byte, v float32) []byte

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

func AppendFloat64(b []byte, v float64) []byte

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

func AppendString(b []byte, s string) []byte

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

func AppendTag(b []byte, fieldNumber uint32, wireType WireType) []byte

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

func AppendVarint(b []byte, v uint64) []byte

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

func ConsumeBytes(b []byte) (data []byte, bytesConsumed int)

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

func ConsumeField(wireType WireType, b []byte) int

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

func ConsumeFixed32(b []byte) (uint32, int)

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

func ConsumeFixed64(b []byte) (uint64, int)

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

func ConsumeFloat32(b []byte) (float32, int)

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

func ConsumeFloat64(b []byte) (float64, int)

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

func ConsumeString(b []byte) (string, int)

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

func ConsumeVarint(b []byte) (value uint64, bytesConsumed int)

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

func DecodeZigZag32(v uint32) int32

DecodeZigZag32 decodes a ZigZag-encoded uint32 back to the original signed int32 value. It reverses the mapping performed by EncodeZigZag32.

func DecodeZigZag64

func DecodeZigZag64(v uint64) int64

DecodeZigZag64 decodes a ZigZag-encoded uint64 back to the original signed int64 value. It reverses the mapping performed by EncodeZigZag64.

func EncodeTag

func EncodeTag(fieldNumber uint32, wireType WireType) uint64

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

func EncodeZigZag32(v int32) uint32

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

func EncodeZigZag64(v int64) uint64

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

func ParseError(n int) error

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

func SizeBytes(dataLen int) int

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

func SizeTag(fieldNumber uint32) int

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

func SizeVarint(v uint64) int

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

func (c *Codec) AppendBytes(b []byte, data []byte) []byte

AppendBytes delegates to the package-level AppendBytes function.

func (*Codec) AppendFixed32

func (c *Codec) AppendFixed32(b []byte, v uint32) []byte

AppendFixed32 delegates to the package-level AppendFixed32 function.

func (*Codec) AppendFixed64

func (c *Codec) AppendFixed64(b []byte, v uint64) []byte

AppendFixed64 delegates to the package-level AppendFixed64 function.

func (*Codec) AppendFloat32

func (c *Codec) AppendFloat32(b []byte, v float32) []byte

AppendFloat32 delegates to the package-level AppendFloat32 function.

func (*Codec) AppendFloat64

func (c *Codec) AppendFloat64(b []byte, v float64) []byte

AppendFloat64 delegates to the package-level AppendFloat64 function.

func (*Codec) AppendString

func (c *Codec) AppendString(b []byte, s string) []byte

AppendString delegates to the package-level AppendString function.

func (*Codec) AppendTag

func (c *Codec) AppendTag(b []byte, fieldNumber uint32, wireType WireType) []byte

AppendTag delegates to the package-level AppendTag function.

func (*Codec) AppendVarint

func (c *Codec) AppendVarint(b []byte, v uint64) []byte

AppendVarint delegates to the package-level AppendVarint function.

func (*Codec) ConsumeBytes

func (c *Codec) ConsumeBytes(b []byte) ([]byte, int)

ConsumeBytes delegates to the package-level ConsumeBytes function.

func (*Codec) ConsumeFixed32

func (c *Codec) ConsumeFixed32(b []byte) (uint32, int)

ConsumeFixed32 delegates to the package-level ConsumeFixed32 function.

func (*Codec) ConsumeFixed64

func (c *Codec) ConsumeFixed64(b []byte) (uint64, int)

ConsumeFixed64 delegates to the package-level ConsumeFixed64 function.

func (*Codec) ConsumeFloat32

func (c *Codec) ConsumeFloat32(b []byte) (float32, int)

ConsumeFloat32 delegates to the package-level ConsumeFloat32 function.

func (*Codec) ConsumeFloat64

func (c *Codec) ConsumeFloat64(b []byte) (float64, int)

ConsumeFloat64 delegates to the package-level ConsumeFloat64 function.

func (*Codec) ConsumeString

func (c *Codec) ConsumeString(b []byte) (string, int)

ConsumeString delegates to the package-level ConsumeString function.

func (*Codec) ConsumeTag

func (c *Codec) ConsumeTag(b []byte) (uint32, WireType, int)

ConsumeTag delegates to the package-level ConsumeTag function.

func (*Codec) ConsumeVarint

func (c *Codec) ConsumeVarint(b []byte) (uint64, int)

ConsumeVarint delegates to the package-level ConsumeVarint function.

func (*Codec) DecodeTag

func (c *Codec) DecodeTag(tag uint64) (uint32, WireType)

DecodeTag delegates to the package-level DecodeTag function.

func (*Codec) DecodeZigZag32

func (c *Codec) DecodeZigZag32(v uint32) int32

DecodeZigZag32 delegates to the package-level DecodeZigZag32 function.

func (*Codec) DecodeZigZag64

func (c *Codec) DecodeZigZag64(v uint64) int64

DecodeZigZag64 delegates to the package-level DecodeZigZag64 function.

func (*Codec) EncodeTag

func (c *Codec) EncodeTag(fieldNumber uint32, wireType WireType) uint64

EncodeTag delegates to the package-level EncodeTag function.

func (*Codec) EncodeZigZag32

func (c *Codec) EncodeZigZag32(v int32) uint32

EncodeZigZag32 delegates to the package-level EncodeZigZag32 function.

func (*Codec) EncodeZigZag64

func (c *Codec) EncodeZigZag64(v int64) uint64

EncodeZigZag64 delegates to the package-level EncodeZigZag64 function.

func (*Codec) SizeBytes

func (c *Codec) SizeBytes(dataLen int) int

SizeBytes delegates to the package-level SizeBytes function.

func (*Codec) SizeTag

func (c *Codec) SizeTag(fieldNumber uint32) int

SizeTag delegates to the package-level SizeTag function.

func (*Codec) SizeVarint

func (c *Codec) SizeVarint(v uint64) int

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

func ConsumeTag(b []byte) (fieldNumber uint32, wireType WireType, bytesConsumed int)

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

func DecodeTag(tag uint64) (fieldNumber uint32, wireType WireType)

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.

func (WireType) String

func (wt WireType) String() string

String returns the human-readable name of the wire type. For the six valid wire types (0-5) it returns names such as "Varint" and "LengthDelimited". For out-of-range values it returns a formatted string like "WireType(6)".

func (WireType) Valid

func (wt WireType) Valid() bool

Valid reports whether wt is one of the six defined protocol buffer wire types (0 through 5 inclusive).

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL