Expand description
Support for code generated by the Graven compiler (and the hand-written code in
graven-schemas that freezes its pattern). Items marked #[doc(hidden)] are called only
by generated code; the rest (ListR, VListR, VStrList, ListW,
StreamW) appear in generated signatures.
All unsafe of the generated pattern lives here and in
TableRef::str_unchecked: [FromVerified::from_verified], VListR::new and
VStrList::new. Generated code has no unsafe blocks of its own beyond calling these
fixed-contract functions, each item carrying #[allow(unsafe_code)] and a // SAFETY:
comment that cites the invariant below.
§Generated pattern (frozen by hand in graven-schemas)
- The caller charges the header. [
FromTable::verify] never charges its own header (2 + fixed_len). The public inherent methodX::verify(&self, ctx)is the “as root” entry point: it charges2 + fixed_lenand callsFromTable::verify;X::verified/X::verified_withonly call the inherentX::verify(they do not charge again). A table/union field charges2 + fixed_lenof the target and calls the child’sFromTable::verify(or the child’s inherentverify, which does both);ListR::verifycharges the elements and callsFromTable::verifyon each one.[string]/[bytes]go through [verify_strs] / [verify_bytes_list]. The totals are those of spec §7.3. - A single kind of view. Every table generates
XVerified<'a>with explicit accessors (neverDeref) andreader(); strings viastr_unchecked, tables viaYVerified, table lists viaVListR,[string]viaVStrList, unions via an enum with anUnknown(u16)that is not descended into. - Every table can be a root.
X::SCHEMA_ID,read,verified,verified_with,from_bytes,XW::root,XW::to_bytes,XW::seal.
§Invariants for the code generator (codegen)
The *Verified views skip UTF-8 validation, relying on the verify() that already
ran. That is only sound if the generated code maintains, for every type X:
- Same edge, same type. An
XVerifiedis only created (via [FromVerified::from_verified]) over a table that the root’sverify()reached successfully along the same edge (same field of the same parent table, same list element) and with the same reader typeX. Being “reachable” is not enough: the same bytes can be pointed to by two edges as tables of different types, andverifyonly validated the type of the edge it walked. str_uncheckedmirrorsstr. Everystr_unchecked(off)call in a view corresponds to a validatingstr(off)call, at the same offset, in that type’sverify. Likewise, everyVStrListin a view corresponds to a [verify_strs] call over the same list (same offset) in that type’sverify; aVStrListis only sound for lists verified byverify_strs.- Nothing beyond what
verifywalks. Views never follow edges thatverifyskips: union tags unknown to the reader, fields beyond the reader’s layout, reserved fields. VListR<T>withverify’sT.VListR::newis only called with the sameTthatverifyused for that list.verifyis#[inline]. The generatedverifyfunctions carry#[inline](its absence once caused a performance regression in verified reads).- Strings validated by
str().verifyMUST validate every string by callingstr()(which checks UTF-8), never by chargingbytes(off).len()to the budget without validating; otherwise item 2 no longer holds.
Items 2 and 6 also hold for [string]: verify MUST call [verify_strs] (never
[verify_bytes_list]) on every list that the view exposes as a VStrList.
The mutation test in graven-schemas/tests/verified.rs
(verified_matches_checked_under_mutation) is the acceptance gate: for mutated messages
that pass verify, every read through the verified view MUST equal the checked read.
Structs§
- ListR
- Typed list of tables; an absent list reads as empty.
- ListW
- Known-count typed list writer.
- StreamW
- Unknown-count typed list writer.
- VListR
- Typed list of verified views; an absent list reads as empty. Only obtainable from a verified view, so its elements are verified too.
- VStr
List [string]inside a verified message:getskips UTF-8 validation. An absent list reads as empty; a0element pointer reads as""(spec §5.6).