Skip to main content

Module tail

Module tail 

Source
Expand description

Hybrid serialization tail for #[hopper::state(dynamic_tail = T)].

Hybrid fixed-head and variable-tail storage keeps hot fields directly addressable while bounding variable data:

Lets Hopper own the fixed-layout hot path while still supporting a dynamic tail for vectors, strings, and optional metadata.

§Wire format

After the layout’s fixed body (offset TYPE_OFFSET + WIRE_SIZE), the tail is encoded as:

[ len: u32 LE ] [ payload: len bytes ]

The fixed-body fast path remains fully zero-copy. code that never touches the tail pays zero overhead. Tail access is explicit (tail_read::<T>() / tail_write::<T>()), which is why the tail is not zero-copy: the typed representation is reconstructed on read and serialized on write.

§Canonical tail encoding (TailCodec)

TailCodec is a minimal Borsh-subset serializer:

  • integers: native little-endian
  • [u8; N]: raw bytes, fixed width
  • bounded byte/string payloads: program-defined length prefix + bytes
  • Option<T>: 1-byte tag (0 = None, 1 = Some) + inner payload

Programs that need richer types (bounded strings, bounded vectors, custom structs) implement TailCodec themselves; the framework does not force a derive or pull Vec / String into the no-alloc runtime surface.

Structs§

BoundedString
Bounded UTF-8 string for Hopper dynamic tails.
BoundedVec
Bounded dynamic vector for Hopper dynamic tails.
SeqTailRead
Read guard over a Seq<T> tail acquired through a Context: owns the shared account byte borrow (narrowed to the tail region) and the segment-registry lease, yielding a TailSeq cursor via seq.
SeqTailWrite
Write guard over a Seq<T> tail acquired through a Context: owns the exclusive account byte borrow (narrowed to the tail region) and the segment-registry lease, yielding a TailSeqMut cursor via seq_mut.
TailBytes
Borrowed final raw-byte tail.
TailSeq
Streaming read cursor over a Seq<T> tail region.
TailSeqIter
Iterator over a TailSeq, yielding one decoded element per step.
TailSeqMut
Streaming write cursor over a Seq<T> tail region.
TailStr
Borrowed final UTF-8 tail.

Constants§

SEQ_LEN_PREFIX
Byte width of the Seq<T> count prefix (u32 LE element count).

Traits§

SeqElement
A TailElement whose encoding has a fixed stride: every value encodes to exactly STRIDE bytes (STRIDE == MAX_ENCODED_LEN, and encode always writes STRIDE).
TailCodec
Canonical serializer for dynamic-tail payloads.
TailElement
Element type accepted by #[tail(vec<T, N>)] in #[hopper::dynamic_account].

Functions§

borrow_address_slice
Borrow one bounded address vector from a compact dynamic-tail payload.
borrow_bounded_str
Borrow one bounded UTF-8 string from a compact dynamic-tail payload.
read_tail
Decode the tail as T: TailCodec, checking that the encoded length exactly matches the u32 prefix. Extra bytes beyond T’s decode are a malformed-encoding signal.
read_tail_len
Read the tail’s u32-LE length prefix.
seq_capacity_for
Live capacity (max element count) of a Seq<T> tail region of region_len bytes: (region_len - 4) / STRIDE. Zero if the region cannot even hold the count prefix.
seq_region_bytes_for
Account allocation (tail region bytes) needed for a Seq<T> of capacity n: 4 + n*STRIDE.
tail_capacity
Return the account bytes available after the tail length prefix.
tail_payload
Return a slice referencing just the tail payload bytes (excluding the 4-byte length prefix). Length-bounded by the u32 prefix.
write_tail
Encode tail into the account’s tail slot, rewriting the u32 length prefix. Returns AccountDataTooSmall when the existing account byte buffer can’t fit the encoded payload. in that case the caller should realloc first.
write_tail_payload
Write an already-encoded dynamic-tail payload.

Type Aliases§

HopperString
Short alias for bounded UTF-8 strings in dynamic tails.
HopperVec
Short alias for bounded vectors in dynamic tails.