Fix H3: field-disc union wire convention — shared-then-variant (review #006)
Decision (recorded as an ADR-011 addendum): the packed-mode wire layout for a field-name-discriminator TUnion is shared-then-variant — the union's declared `fields` (disc + shared fields) first, then the variant's own fields. Reader and materializer already implemented this; LayoutBuilder was corrected from variant-only layout. Enforcement in BastUnion::parse (the choke point every consumer inherits — union roots at BastDoc::new, referenced unions at resolve_ref): - discriminator field must be declared in `fields` - `fields` must not contain duplicate names - variants must not re-declare shared fields (checked inline and through $ref resolution — parse chain now threads the doc root) - the discriminator field must be the FIRST entry in `fields` (the reader reads the disc at the union start; a later position made it dispatch on the wrong bytes — H3 item 2, probe-verified) Schemas relying on the old variant-only builder convention (variants re-declaring shared fields) are rejected with a clean Schema error naming the convention. Breaking for 0.2.0-era re-declaring schemas; announced with 0.3.x. - L5: FieldValue::Union::variant_start doc now states per-kind semantics (byte-disc: union_start + disc.offset + disc.size; field-disc: after the shared walk). - L6: roundtrip test added (poc_roundtrip.rs) — LayoutBuilder write → SequentialReader read → materialize_packed → validate_bytes over a field-disc union with a second shared field and non-redeclaring variant; pins event.type@0/seq@1/handle@5, total 10. - ADR-011: Status-block addendum recording the convention decision, the no-re-declare rule, and the breaking-constraint note. - Review #006 updated: H3/L5/L6 resolution blocks, resolution log, recommended order. Verified: 488 tests green (410+17+34+15+12, 2 pre-existing ignored), clippy -D warnings clean, wasm32 build green, cargo doc zero warnings.
This commit is contained in:
1 parent
2d166f567b
commit
05a2a42983
7 files changed
+561
-44
No files matched your search
@@ -24,6 +24,31 @@ are pre-implementation refinements to types that do not yet exist on
|
||||
`main`; the ADR-011 decision (a compiled `ReadPlan` for packed reads)
|
||||
is unchanged.
|
||||
|
||||
**Addendum — field-disc union wire convention (2026-09-02, review #006
|
||||
H3):** the packed-mode wire layout for a field-name-discriminator
|
||||
TUnion is **shared-then-variant**: the union's declared `fields` (the
|
||||
discriminator field + any shared fields) occupy the union's start
|
||||
offset in declaration order, and the selected variant's fields follow
|
||||
immediately after all shared fields. All three packed-mode consumers
|
||||
now implement this one convention: the reader and materializer already
|
||||
walked `shared` then the variant (the `shared` sub-plan shape above);
|
||||
`LayoutBuilder` was corrected in the same pass — it previously laid out
|
||||
only the selected variant, disagreeing with the read side on span and
|
||||
field positions (review #006 H3 item 1). The convention requires that
|
||||
a variant **must not re-declare** the discriminator field or any
|
||||
shared field — `BastUnion::parse` enforces this at parse time (also:
|
||||
the discriminator field must be declared in `fields`, and `fields`
|
||||
must not contain duplicate names), so the shared walk and the variant
|
||||
walk cover disjoint fields and the wire has exactly one copy of each
|
||||
shared byte. Schemas whose variants redeclared shared fields were
|
||||
ambiguous under the old split-convention behavior and are rejected
|
||||
rather than given a silent meaning; this is a **breaking wire-format
|
||||
constraint** for any 0.2.0-era schema that relied on re-declaration,
|
||||
announced with the 0.3.x series. `DiscriminatorPlan::Field`'s disc
|
||||
read is at the disc field's position within the shared walk (the
|
||||
materializer's position-correct behavior, review #006 H3 item 2); the
|
||||
reader's plan-walk reads it there too.
|
||||
|
||||
## Context
|
||||
|
||||
Review #004 (`docs/reviews/004-performance-review.md`) measured the
|
||||
|
||||
Reference in new issue
Block a user