Low-level schema language¶
rustruct.compile() accepts field tuples and returns a
rustruct.Codec that packs mappings and unpacks dictionaries.
Field tuples¶
A field is (name, kind, options) – any 3-element tuple works, including
rustruct.Field, a NamedTuple provided for exactly this: it reads
better than three unlabeled positions, and it’s still a plain tuple
underneath (the Rust core downcasts it structurally), so nothing else has to
change:
from rustruct import Field, compile
codec = compile(
(
Field(name="tag", kind="u8", opts={}),
Field(name="length", kind="u16", opts={}),
Field(name="data", kind="bytes", opts={"len": ("ref", "length")}),
),
byteorder="big",
)
wire = codec.pack({"tag": 7, "data": b"abc"})
assert wire == b"\x07\x00\x03abc"
assert codec.unpack(wire) == {
"tag": 7,
"length": 3,
"data": b"abc",
}
A bare tuple like ("tag", "u8", {}) works exactly the same way.
Common kinds are:
fixed scalars:
u8/i8throughu64/i64,f32,f64,bool;raw,bytes,str, andcstr;bitsandflags;struct,array,cond, andswitch;digest.
The declarative frontend lowers to this same vocabulary.
Expressions¶
Options use explicit expression tuples:
("ref", "length")
("sub", ("ref", "total_length"), 20)
("mul", ("sub", ("ref", "ihl"), 5), 4)
The frontend’s strings and lambdas compile to these expressions.
Codec operations¶
pack(mapping) -> bytespack_into(buffer, offset, mapping) -> new_offsetunpack(buffer) -> dictunpack_from(buffer, offset) -> (dict, new_offset)parse(buffer, offset) -> (dict, new_offset) |rustruct.Incomplete
min_size is a lower bound.
static_size is an exact size for
fully static schemas and None otherwise.
Streaming¶
parse() never treats a mere data shortage
as malformed:
from rustruct import Incomplete
result = codec.parse(b"\x07")
assert isinstance(result, Incomplete)
Incomplete.needed is the minimum
additional byte count known at that point.
Limits¶
max_default limits dynamic fields without a smaller explicit maximum.
max_count limits array elements. Both defaults are intentionally finite.
Extension boundary¶
The set of core field kinds is closed in this release. There is no public
Python custom-codec base that runs inside the native program.
rustruct.convert() provides value-level transformation. Algorithms
that require absolute buffer offsets or cross-message state require
composition outside the native program. See
Extension model.