Files
zeekay bfaa9812dd v1/codegen: emit singular NESTED object fields (zero-copy, typed)
Completes the variable-length codegen (strings/bytes/lists/nested) — the
last shape needed before protoc-gen-zap can map every proto message field
mechanically.

Runtime (v1/nested.go):
- NestedAt[S,N]: read an out-of-line 4-byte object pointer as a typed
  View[N]; null/OOB -> zero View (proto3 unset).
- WriteNested[S,N]: build a flat nested object into the parent tail and
  patch the pointer; the singular peer of WriteList. Composes recursively
  (nested may carry scalars, strings, bytes, lists, further nesting).

Codegen (schema.go, emit.go):
- Field.Nested *NestedMsg (4-byte object pointer, distinct from the 8-byte
  list/tail pointer); IsNested().
- Constructor takes *Value (nil => null), nil-guarded WriteNested build.
- emitNestedSupport: value struct + NestedAt read accessor.
- emitElemWrites: shared scalar/string/bytes element-write body, so list
  elements now also support string/bytes sub-fields (repeated-of-message).
- ListElem/NestedMsg carry Wire (element WireName) for Offset<Wire>_<F>.

Proven end-to-end: runtime roundtrip (nested w/ own string tail + null
case), generator-output tests (go/parser-valid), and a generated-code wire
roundtrip (testpkg/nestwire). Full v1+codegen suite green, no regression.
2026-06-23 16:28:51 -07:00

112 lines
3.8 KiB
Go

// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
//
// Code generated by github.com/luxfi/zap/v1/codegen — DO NOT EDIT.
// Source schema: Outer (kind=0x51, size=13).
package nestwire
import (
"github.com/luxfi/zap"
zapv1 "github.com/luxfi/zap/v1"
)
// KindOuter is the wire discriminator for Outer.
const KindOuter zapv1.KindByte = 0x51
// SizeOuter is the fixed object payload size in bytes.
const SizeOuter = 13
// OuterSchema is the v1 schema marker for Outer. Methods are constant-
// returning so concrete-typed [zapv1.Wrap[OuterSchema]] calls fold to
// literals at the call site.
type OuterSchema struct{}
func (OuterSchema) Kind() zapv1.KindByte { return KindOuter }
func (OuterSchema) Size() int { return SizeOuter }
func (OuterSchema) Name() string { return "Outer" }
// OffsetOuter_Seq is the byte offset of the Seq field.
const OffsetOuter_Seq = 1
// OffsetOuter_Inner is the byte offset of the Inner field.
const OffsetOuter_Inner = 9
// OuterSchemaFields is the namespace of every scalar field accessor for Outer.
// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.
// Byte-array fields are emitted as standalone functions, see below.
var OuterSchemaFields = struct {
Seq zapv1.Field[OuterSchema, uint64]
}{
Seq: zapv1.At[OuterSchema, uint64](1),
}
// NewOuter builds a fresh Outer in a ZAP buffer.
//
// Hand-rolled fast path: inlines v1 primitives ([zap.NewBuilder],
// [*Builder.StartObject], [*ObjectBuilder.Set*], [*Builder.Finish])
// so the entire build expands at the call site. Scalars and fixed byte
// arrays live in the fixed payload; variable-length string/bytes go in
// the object tail (the fixed payload holds their 8-byte pointers).
func NewOuter(seq uint64, inner *Inner) (zapv1.View[OuterSchema], []byte) {
b := zap.NewBuilder(zap.HeaderSize + SizeOuter)
ob := b.StartObject(SizeOuter)
ob.SetUint8(0, uint8(KindOuter))
ob.SetUint64(OffsetOuter_Seq, seq)
ls := zapv1.SetterFrom[OuterSchema](ob, b)
if inner != nil {
zapv1.WriteNested[OuterSchema, InnerSchema](ls, OffsetOuter_Inner, func(e zapv1.Setter[InnerSchema]) {
zapv1.Write(e, InnerSchemaFields.ID, inner.ID)
zapv1.WriteString(e, OffsetInner_Label, inner.Label)
})
}
rootOff := ob.FinishAsRoot()
buf := b.Finish()
end := rootOff + SizeOuter
return zapv1.AsView[OuterSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
}
// WrapOuter parses a ZAP buffer into a typed
// [zapv1.View[Outer]]. Validates the wire frame and the kind
// discriminator at offset 0; returns [*zapv1.SchemaError] on kind
// mismatch.
//
// Hand-rolled fast path: inlines [zap.Parse] (which is itself
// inlineable). Zero heap allocs on the happy path; matches v1
// hand-rolled performance.
func WrapOuter(b []byte) (zapv1.View[OuterSchema], error) {
msg, err := zap.Parse(b)
if err != nil {
return zapv1.View[OuterSchema]{}, err
}
root := msg.Root()
if got := root.Uint8(0); got != uint8(KindOuter) {
return zapv1.View[OuterSchema]{}, zapv1.NewSchemaError(
KindOuter, zapv1.KindByte(got), "Outer")
}
data := msg.Bytes()
rootOff := root.Offset()
end := rootOff + SizeOuter
if end > len(data) {
end = len(data) // Read returns zero on OOB; v1 graceful degradation
}
return zapv1.AsView[OuterSchema](zapv1.RawFromSlices(data, rootOff, end)), nil
}
// Inner is the value input for the singular Outer.Inner nested object.
type Inner struct {
ID uint64
Label string
}
// OuterInner returns the singular Inner nested object of Outer as a
// zero-copy [zapv1.View][InnerSchema]. An unset (null) nested field yields the zero
// View — test it with [zapv1.View.IsZero].
func OuterInner(v zapv1.View[OuterSchema]) zapv1.View[InnerSchema] {
return zapv1.NestedAt[OuterSchema, InnerSchema](v, OffsetOuter_Inner)
}
func init() {
zapv1.Register[OuterSchema](zapv1.DefaultRegistry)
}