A strict, bidirectional codec for a single string token. decode returns
null when the token is not valid for this codec — that null is what lets the
caller fall through (URL match fallthrough, or best-effort restore). encode
is the exact inverse for any value the codec can produce, so a value
round-trips to the same canonical token.
A composite codec (see Codec.composite); const-constructible. Components
are individual fields — a const constructor can't build a list — so the
signature itself caps the arity at 16. The value is a positional RECORD of
the components' decoded values: a record's runtime type comes from its
fields' runtime types, so a 2-part composite of string codecs decodes to a
value that IS a (String, String) — typed casts and structural equality
(repeat-collapse, prefix reuse) work as if it were declared that shape.
See IdNode.compose. Component nodes are individual fields — a const
constructor can't build a list — so the signature itself caps the arity at
16 (à la Object.hash); generators read the n* fields directly.
An ordered sequence of codecs occupying ONE path segment: exactly one
VARIABLE member (carries the value) framed by LiteralCodec members
(fixed text). Invertible because the literals anchor the boundaries —
decode strips the leading/trailing literals, delegates the remainder to the
variable. A second variable has no recoverable boundary, so it is rejected.
The contract an @ids enum wears: every row carries a codec. The node IS a
Codec (it delegates to its inner one), so a screen can bind it straight into
a Codec? id field (id: .user) and a store can key by it — the SAME node
across both grammar trees. Generators read node.codec to recover the value
type (the node itself erases to Codec<Object?>).
Marks the HAND-WRITTEN enum that is an app's id-space: each row is an identity
carrying its Codec — how its key serialises in a URL. Nothing is generated;
the enum IS the holder. Other grammar trees (canon's @screens, ledger's
@stores) reference these rows by dot-shorthand and read row.codec to
encode/decode and to validate a screen id or a store key against them.
The flattened branches of an a | b | c union. Decode tries them left-to-
right (first non-null wins); encode uses the left/canonical branch. The
nav/link layer reads branches to recover the ordered union the spec wrote.
Adds (#name) to a codec, overriding a generated field name at the use site
(slot(.uuid(#productId))). The returned codec drops the mixin, so a name can be
applied at most once. Battery codecs mix this in; custom codecs may.
+ is ORDERED concatenation within one segment — the string forms of the
members joined in order (Ids.image + Codec.literal('_thumb') →
{imageId}_thumb). Non-commutative on purpose (prefix ≠ suffix), unlike the
commutative |. Exactly one member carries a value; literals frame it.
a | b — a union: either token addresses the same T. Decode tries the
branches left-to-right (strict codecs return null on a non-match, so the
first that accepts the token wins); encode delegates to the left branch (the
canonical form). The nav/link generator reads the branches structurally; this
runtime form lets a spec written with | compile and round-trip. An
extension, not an interface member, so existing implements Codec classes
are unaffected.