How to compile mapping-based schemas¶
Build the field sequence¶
Use the low-level API when field declarations are generated at runtime or when
the application wants dictionaries instead of typed rustruct.Struct
instances.
Create one Field(name, kind, opts) tuple per wire
field:
from rustruct import Field, compile
fields = (
Field(name="kind", kind="u8", opts={}),
Field(name="length", kind="u16", opts={}),
Field(name="payload", kind="bytes", opts={"len": ("ref", "length")}),
)
codec = compile(fields, byteorder="big")
The reference from payload makes length a derived field during pack.
Pack and unpack mappings¶
wire = codec.pack({"kind": 3, "payload": b"hello"})
assert wire == b"\x03\x00\x05hello"
decoded = codec.unpack(wire)
assert decoded == {
"kind": 3,
"length": 5,
"payload": b"hello",
}
Use pack_into() or
unpack_from() when the value occupies
part of an existing buffer. Use parse() when
a short buffer should return rustruct.Incomplete instead of
raising an invalid-data error.
Apply safety limits¶
Pass max_default to cap dynamic byte fields without a smaller field-specific
maximum, and max_count to cap arrays:
limited_codec = compile(
fields,
byteorder="big",
max_default=1024 * 1024,
max_count=4096,
)
assert limited_codec.min_size == 3
See Low-level schema language for every field kind, expression form, operation, and size attribute.