# Codec contracts and built-ins
A codec owns one field's exact wire representation. Layout generation owns physical
order, represented extent, framing, bounded ranges, and caller storage; consumers own
domain policy such as magic values, reserved ranges, checksums, and cross-field rules.
## Choose a contract
- Implement [`FixedCodec`] when every value has one compile-time, nonzero width.
Decode every exact-width bit pattern; do not make application semantics a required
structural-validation step. Declare such a codec directly with `name: path::Codec;`.
- Implement [`PrefixCodec`] when bounded structural validation must discover the
nonzero encoded width from available input. `validate_prefix` receives the remaining
bytes and decoding then receives exactly the accepted span. Declare it with
`name: variable(path);`.
- Implement [`EncodePlan`] as the result of fallible `plan`. Its `encoded_len` and
`write_into` must describe the same representation, and writing into its exact-sized
destination must be infallible.
A self-delimiting view retains its accepted extent. Its raw getter returns those
original bytes, including a legal noncanonical encoding; it does not reconstruct them
from the decoded value. A self-delimiting plan may choose a canonical encoding for a
value.
## Builder boundary
Generated setters and builders use plans to preserve atomic caller-buffer updates.
Before a builder writes, it completes all fallible planning, plan-length checks,
derivations, endpoint calculations, arithmetic, and capacity checks. A returned build
error therefore leaves the complete supplied output slice unchanged.
Generated code defensively verifies claims that affect safe slicing and atomicity, but
a custom codec that violates its trait laws is still broken. In particular:
- `FixedCodec::WIDTH` is nonzero, and every successful fixed plan is exactly that width.
- `PrefixCodec::validate_prefix` returns a nonzero extent within its supplied input.
- Every successful self-delimiting plan is nonempty.
- A successful plan encodes the semantic value it planned.
Keep framing between fields, range-source algebra, derived endpoints, and protocol
validation outside a codec. A self-delimiting codec discovers its own field width; it
is not a source for a later dynamic byte range.
## Range-source adapters
[`RangeSource`] performs checked bidirectional structural conversion between a decoded
fixed source representation and byte geometry. `to_bytes` supplies either a relative
length or an exclusive representation-relative endpoint while parsing; `from_bytes`
canonicalizes the encoded source from builder-requested geometry during preparation.
Supported values and geometries must round-trip coherently, with checked arithmetic
and an explicit conversion error. The trait does not decide protocol policy.
For a `range_source: Adapter` macro field, parsing calls `to_bytes` at each consuming
range before normal checked range/bounds validation. Preparation derives geometry,
requires shared consumers to agree by geometry, converts once per source with
`from_bytes`, then plans the physical codec. Commit only checks capacity and writes the
prepared plan, preserving atomic caller-output updates. No API retains contradictory or
noncanonical source values.
Macro adapters are restricted to direct built-in integer fixed fields that physically
precede a consumed range. They cannot coexist with mappings, derivation, or
finalization. Unsigned bit projections may coexist and read the same whole packed
integer consumed and returned by the adapter. This hard ownership boundary avoids
custom `FixedCodec` values or plans whose borrows would require self-referential prepared
storage. The source getter is still its raw wire integer; adapters do not add a
byte-geometry getter. Checked structural underflow, alignment, and encoded-field bounds
belong to the adapter; unrelated protocol semantics remain consumer-owned.
## Built-ins
This module provides [`U8`] and [`I8`], big- and little-endian unsigned
16/24/32/64/128-bit codecs, big- and little-endian signed 16/32/64/128-bit codecs,
and [`Bytes<N>`](Bytes) for an opaque exact-width borrowed span.
Unsigned 24-bit codecs use `u32` semantic values and reject values greater than
`0x00ff_ffff` while planning. `Bytes<N>` requires `N > 0`; building checks that an
input has exactly `N` bytes before mutation.