protocol

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package protocol provides a wire-protocol foundation for custom binary protocols: framed messages with versioned magic + sequence + opcode, encoding helpers (varint, quantised float), and a typed opcode registry where projects bind their per-opcode payload codecs.

Domain-agnostic; common applications:

  • Custom UDP / TCP application protocols.
  • Market-data feeds with fixed-shape per-tick messages.
  • Sensor / IoT telemetry with bandwidth-constrained encodings.
  • Cross-language protocols requiring byte-for-byte parity (the frame format is stable; golden vectors under kit/protocol/golden/ support cross-language parity testing — for example, against a matching C++ implementation in a paired client SDK).

Index

Constants

This section is empty.

Variables

View Source
var ErrUnknownOpcode = errors.New("protocol: unknown opcode")

ErrUnknownOpcode is returned when decoding a frame whose opcode has no registered codec.

Functions

func ReadQuantFloat

func ReadQuantFloat(r *bytes.Reader, bits uint8) (float32, error)

ReadQuantFloat reads a value previously written with WriteQuantFloat.

func ReadVarUint

func ReadVarUint(r *bytes.Reader) (uint64, error)

ReadVarUint reads an unsigned LEB128 varint.

func Register

func Register[T any](r *Registry, op Opcode, name string, enc func(T, *bytes.Buffer), dec func(*bytes.Reader) (T, error))

Register binds typed encode + decode functions to an opcode. Name is used for diagnostics.

func WriteQuantFloat

func WriteQuantFloat(buf *bytes.Buffer, f float32, bits uint8)

WriteQuantFloat writes f as a quantised value using bits ∈ {16, 32}. 32-bit is IEEE 754 raw; 16-bit is bfloat16 (top 16 bits of float32), chosen because both endpoints round-trip identically.

func WriteVarUint

func WriteVarUint(buf *bytes.Buffer, v uint64)

WriteVarUint emits v as an unsigned LEB128 varint. Matches the encoding used by Google protobuf wire format (and our C++ side).

Types

type Codec

type Codec struct {
	// contains filtered or unexported fields
}

Codec encodes / decodes Frames against a fixed Magic + Version. Wrong magic or version on decode returns an error.

func NewCodec

func NewCodec(magic [2]byte, version uint8) *Codec

NewCodec returns a Codec for the given magic + version pair.

func (*Codec) Decode

func (c *Codec) Decode(in *bytes.Reader) (Frame, error)

Decode reads a Frame from in. Consumes the entire remaining buffer as payload (caller controls outer framing for stream transports). The returned Frame.Payload is a freshly-allocated slice; callers that need zero-allocation should use DecodeInto.

func (*Codec) DecodeInto

func (c *Codec) DecodeInto(in *bytes.Reader, payloadBuf []byte) (Frame, error)

DecodeInto reads a Frame from in, reusing payloadBuf for the payload allocation. If payloadBuf has sufficient capacity, no allocation occurs; otherwise a new slice grows behind it. Pass nil to behave like Decode (allocates a fresh slice each call).

func (*Codec) Encode

func (c *Codec) Encode(f Frame, out *bytes.Buffer) error

Encode writes a Frame into out using little-endian byte order.

type Frame

type Frame struct {
	Magic   [2]byte
	Version uint8
	Flags   uint8
	Seq     uint32
	Opcode  Opcode
	Payload []byte
}

Frame is the wire-level message: a 10-byte header followed by Payload.

bytes  | field
-------+----------
0..1   | Magic (uint8 × 2, e.g. "FG")
2      | Version (uint8)
3      | Flags   (uint8)
4..7   | Seq     (uint32, little-endian)
8..9   | Opcode  (uint16, little-endian)
...    | Payload (Length implicit from outer frame size)

type Opcode

type Opcode uint16

Opcode identifies a payload type within a frame.

type ReaderPool

type ReaderPool struct {
	// contains filtered or unexported fields
}

ReaderPool pools *bytes.Reader instances so callers can decode many frames without allocating a new Reader per call. Pair with DecodeInto + a recycled payload buffer for fully zero-alloc decoding.

func NewReaderPool

func NewReaderPool() *ReaderPool

NewReaderPool returns an empty pool. The pool is safe for concurrent use.

func (*ReaderPool) Get

func (p *ReaderPool) Get(data []byte) *bytes.Reader

Get returns a Reader positioned over data. Always return it via Put.

func (*ReaderPool) Put

func (p *ReaderPool) Put(r *bytes.Reader)

Put returns a Reader to the pool.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry maps Opcodes to per-type encode/decode functions. Callers register their typed payload codecs via the generic Register helper.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty registry.

func (*Registry) DecodePayload

func (r *Registry) DecodePayload(op Opcode, payload []byte) (any, error)

DecodePayload looks up the codec for op and decodes from payload bytes.

func (*Registry) EncodePayload

func (r *Registry) EncodePayload(op Opcode, v any) ([]byte, error)

EncodePayload looks up the codec for op and encodes v into a new buffer.

func (*Registry) Name

func (r *Registry) Name(op Opcode) string

Name returns the opcode's registered name, or empty string if unknown.

Jump to

Keyboard shortcuts

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