ReadonlycapReadonlymakeReadonlynameReadonlyoutReadonlyreceiverThe two index bounds, without growing — see ElementSeq.checkIndex.
Split out for the same reason it is there: a caller may have a second bound
to take before anything is allocated. A native matrix row is that case in this
port — its element count is rejected at the array header, and §7.2 item 8
wants that rejection to leave the row container exactly as it was.
Bound-check id, fill the gap below it, then write value into the slot —
what a nested row needs, an array wrapper replacing whatever an earlier
opening built at that index (§7.4) rather than merging into it.
The gap fill stops one short of id on purpose: the slot is about to be
overwritten, so calling make() for it would allocate an element default
nobody ever reads. Assigning at out.length extends the array by exactly one,
which is the same array a reserve would have left.
Bound-check id, then grow out to id + 1, each new slot its own
make().
The order is §7.2 item 8's "after a rejected id the container is not left
partially extended": a rejection leaves out exactly as it was, so a lower id
delivered afterwards still lands at its own index. A slot already present is
left alone — a re-opened struct / union element merges into the object it
already built, which is what §7.4's last-occurrence-wins means for a scope
whose value is the scope.
The slots of a wrapper-sequence array whose element default is a fresh object: a framed element (
struct/union) or a nested row.ElementSeq's twin, and it differs in exactly one thing — the gap value comes from a factory instead of being shared. That single axis is why it is a second class rather than a second argument: a framed element's default is
new Elem()and a row's is[], both mutable and both reachable by the caller, so one shared instance would alias every gap of the array onto it and — since an arriving element decodes into the slot the reservation placed — would alias every element onto it too, which is not a near miss but a flatly wrong decode. ElementSeq's""and zero-lengthUint8Arrayhave no state to share, which is what makes sharing right there and wrong here.Everything else is ElementSeq, deliberately: the same argument order with
makeindef's slot, the same two exclusive index bounds through the sameindexBound/rejectIndexpair, the same growth geometry, the same construction-time refusal of a receiver cap that states no cap.Generated code calls reserve at the element's own
sequenceBeginand then keeps routing the child's fields intoout[id]itself. This class owns the bound and the growth; it never owns the routing, which is the part that has a different shape for every schema (ARCHITECTURE §8).Param: out
The destination array; grown to
id + 1as elements arrive.Param: make
Builds one element default. Called once per gap slot, and once for the reserved slot itself in reserve — never for a slot already present, so a re-opened element keeps the object earlier fields decoded into.
Param: cap
The schema
countas an index capacity:id >= capisINVALID(§7.1) — a statement about validity. Pass UNBOUNDED (-1) for an array the schema left open, wherereceiverCapgoverns instead.Param: name
The schema field name, used only in a rejection message.
Param: receiverCap
The receiver-side index cap for a schema-unbounded array (§6.2.1):
id >= receiverCapisLIMIT_EXCEEDED, a policy rejection, neverINVALID, and never applied beside acapthe schema stated. Required, with no default; a value that states no cap at all isArgumentat construction (requireReceiverBound).