Codecs

Names on this page are imported from bytespec.codecs. A codec accepts and returns a single value; only ModelCodec adds a model header. Examples: Codecs: custom formats and types.

Common interface

class bytespec.codecs.ICodec(*args: Any, **kwargs: Any)[source]

Interface for writing and reading a single value of type T.

An instance can be passed to field(codec=...). Inheriting from ICodec is optional: encode and decode methods that follow this contract are sufficient. A codec can be reused; the read position is passed through offset.

decode returns the value and the absolute offset after it. When using a codec directly, the caller is responsible for checking any remaining bytes. In a custom codec, report data errors through EncodeError and DecodeError.

encode(value: T, byte_order: ByteOrder, /) bytes[source]

Write a single value in the selected representation.

Parameters:
  • value – The value to write.

  • byte_order – The byte order of fixed-width numbers and prefixes.

Returns:

The binary representation of the value.

Raises:

EncodeError – The value cannot be represented. A custom codec must raise this error itself for data errors.

decode(buffer: bytes, byte_order: ByteOrder, offset: int, /) tuple[T, int][source]

Read a single value starting at offset.

Parameters:
  • buffer – The buffer containing the encoded value.

  • byte_order – The byte order of fixed-width numbers and prefixes.

  • offset – The nonnegative absolute position where the value starts.

Returns:

The value and the absolute position after it in the same buffer. The remaining bytes do not have to be consumed.

Raises:

DecodeError – There are not enough bytes, or the value is invalid. The implementation must check bounds and contents itself.

Note

A list item codec must advance offset by a positive number of bytes while staying within the supplied buffer.

Implementation requirements

decode() must return the absolute position after the value in the same buffer and check that the required bytes are available. A codec instance can be reused: keep the position in the arguments and return value, rather than in a mutable internal counter.

A list item must advance the position by a positive number of bytes within the supplied buffer. ListCodec reads repeatedly until the end of its contents and does not check offset progress itself. Zero-length items, such as FixedBytesCodec(0), are unsuitable: their count cannot be recovered from empty contents.

Report data errors through EncodeError and DecodeError. Implementation errors such as TypeError or ValueError are not wrapped. The ICodec protocol check verifies that the methods exist, but does not validate their signatures or implementation.

Fixed-width numbers

All numeric codecs use the encode/decode interface from ICodec. Use the default struct_format and length values shown: changing them manually requires keeping the struct size and decoder step consistent. The constructor checks format syntax, but does not check that these parameters agree.

class bytespec.codecs.UInt8Codec(struct_format: str = 'B', length: int = 1)[source]

Unsigned 8-bit integer: 0–255, one byte by default.

class bytespec.codecs.UInt16Codec(struct_format: str = 'H', length: int = 2)[source]

Unsigned 16-bit integer: 0–65535, two bytes by default.

class bytespec.codecs.UInt32Codec(struct_format: str = 'I', length: int = 4)[source]

Unsigned 32-bit integer: 0 .. 2**32 - 1, four bytes.

class bytespec.codecs.UInt64Codec(struct_format: str = 'Q', length: int = 8)[source]

Unsigned 64-bit integer: 0 .. 2**64 - 1, eight bytes.

class bytespec.codecs.Int8Codec(struct_format: str = 'b', length: int = 1)[source]

Signed 8-bit integer: -128–127, one byte by default.

class bytespec.codecs.Int16Codec(struct_format: str = 'h', length: int = 2)[source]

Signed 16-bit integer: -32768–32767, two bytes by default.

class bytespec.codecs.Int32Codec(struct_format: str = 'i', length: int = 4)[source]

Signed 32-bit integer: -2**31 .. 2**31 - 1, four bytes.

class bytespec.codecs.Int64Codec(struct_format: str = 'q', length: int = 8)[source]

Signed 64-bit integer: -2**63 .. 2**63 - 1, eight bytes.

class bytespec.codecs.Float32Codec(struct_format: str = 'f', length: int = 4)[source]

IEEE 754 binary32: four bytes, rounding the Python float.

class bytespec.codecs.Float64Codec(struct_format: str = 'd', length: int = 8)[source]

IEEE 754 binary64: eight bytes in the model’s byte order.

Varint and bool

class bytespec.codecs.VarUIntCodec(*args: Any, **kwargs: Any)[source]

Canonical unsigned varint: 0 .. 2**64 - 1, 1 to 10 bytes.

Groups of 7 bits are written starting with the least significant. The model’s byte order does not affect this representation.

Canonical unsigned varint in the UInt64 range.

class bytespec.codecs.VarIntCodec(*args: Any, **kwargs: Any)[source]

Signed varint: ZigZag + unsigned varint in the Int64 range.

Uses 1–10 bytes regardless of the model’s byte order.

ZigZag + unsigned varint in the Int64 range.

class bytespec.codecs.BoolCodec(*args: Any, **kwargs: Any)[source]

A Boolean value in one byte: 0 or 1.

Writes the truth value as 0/1; accepts only 0/1 when reading.

Strings, bytes, datetime, and UUID

class bytespec.codecs.StrCodec(prefix_length: Literal[1, 2, 4, 8] | Annotated[int, VarIntSpec(signed=False)] = 4, encoding: str = 'utf-8')[source]

Text prefixed with the length in encoded bytes, not characters.

Parameters:
  • prefix_length – Prefix size: 1, 2, 4, or 8 bytes, or VarUInt. Defaults to 4 bytes.

  • encoding – Python encoding, UTF-8 by default.

Raises:

SchemaError – Unsupported prefix or unknown encoding.

The encoded byte count as a prefix, followed by text in the selected encoding.

class bytespec.codecs.BytesCodec(prefix_length: Literal[1, 2, 4, 8] | Annotated[int, VarIntSpec(signed=False)] = 4)[source]

Bytes prefixed with their length.

Parameters:

prefix_length – Prefix size: 1, 2, 4, or 8 bytes, or VarUInt. Defaults to 4 bytes. The prefix itself is not included in the stored length.

Raises:

SchemaError – Unsupported prefix, including VarInt.

A length prefix followed by the bytes contents.

class bytespec.codecs.FixedBytesCodec(length: int)[source]

Exactly length bytes without a length prefix.

Parameters:

length – The nonnegative fixed size of the value.

Raises:

SchemaError – Negative length.

Exactly length bytes without a prefix. The length must be nonnegative.

class bytespec.codecs.DatetimeCodec(prefix_length: Literal[1, 2, 4, 8] | Annotated[int, VarIntSpec(signed=False)] = 4, encoding: str = 'utf-8')[source]

A datetime as a length-prefixed ISO 8601 string.

Preserves the UTC offset from isoformat(), but not the time zone name. A datetime without tzinfo remains naive after reading.

Parameters:
  • prefix_length – Prefix size: 1, 2, 4, or 8 bytes, or VarUInt.

  • encoding – Encoding of the ISO string, UTF-8 by default.

Raises:

SchemaError – Unsupported prefix or unknown encoding.

datetime.isoformat() via StrCodec; read using datetime.fromisoformat().

class bytespec.codecs.UUIDCodec[source]

A UUID as exactly 16 bytes from UUID.bytes, without a length prefix.

The model’s byte order does not switch this representation to bytes_le.

Exactly 16 bytes from UUID.bytes, regardless of the model’s byte order.

Composite values

class bytespec.codecs.ListCodec(item_codec: ICodec[Any], prefix_length: Literal[1, 2, 4, 8] | Annotated[int, VarIntSpec(signed=False)] = 4)[source]

A list prefixed with the total size of its encoded items in bytes.

Parameters:
  • item_codec – The codec for a single item. When reading, it must advance offset by a positive number of bytes within the supplied buffer.

  • prefix_length – Prefix size: 1, 2, 4, or 8 bytes, or VarUInt. Defaults to 4 bytes. The prefix does not store the item count.

Raises:

SchemaError – Unsupported length prefix.

A prefix containing the total payload length in bytes. item_codec must read one item per call and advance offset within the buffer bounds.

class bytespec.codecs.EnumCodec(enum_type: type[Enum], value_codec: ICodec[Any])[source]

An enum encoded using a codec for its value.

Parameters:
  • enum_type – The enum class used to reconstruct members via enum_type(value).

  • value_codec – The codec for .value, such as StrCodec or UInt8Codec.

Encodes .value using the supplied value_codec and reconstructs the member by calling enum_type(value).

class bytespec.codecs.ModelCodec(model_type: type[ProtoModel])[source]

A nested model with its own framing, excluding Constructor, and its own byte order.

Parameters:

model_type – The concrete class to read via decode_from(). Subclasses are not selected automatically by constructor.

Calls encode(include_constructor=False) and model_type.decode_from(..., expect_constructor=False). The model uses its own byte order and header, omitting Constructor. Other elements are retained. The nested model type is determined by the annotation.