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.decodereturns 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 throughEncodeErrorandDecodeError.- 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.
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
UInt64range.
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
bytescontents.
- 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
lengthbytes 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()viaStrCodec; read usingdatetime.fromisoformat().
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_codecmust 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
.valueusing the suppliedvalue_codecand reconstructs the member by callingenum_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)andmodel_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.