mirror of
https://github.com/luxfi/zap.git
synced 2026-10-30 15:04:16 +00:00
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.
98 lines
3.3 KiB
Go
98 lines
3.3 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: Inner (kind=0x52, size=16).
|
|
|
|
package nestwire
|
|
|
|
import (
|
|
"github.com/luxfi/zap"
|
|
zapv1 "github.com/luxfi/zap/v1"
|
|
)
|
|
|
|
// KindInner is the wire discriminator for Inner.
|
|
const KindInner zapv1.KindByte = 0x52
|
|
|
|
// SizeInner is the fixed object payload size in bytes.
|
|
const SizeInner = 16
|
|
|
|
// InnerSchema is the v1 schema marker for Inner. Methods are constant-
|
|
// returning so concrete-typed [zapv1.Wrap[InnerSchema]] calls fold to
|
|
// literals at the call site.
|
|
type InnerSchema struct{}
|
|
|
|
func (InnerSchema) Kind() zapv1.KindByte { return KindInner }
|
|
func (InnerSchema) Size() int { return SizeInner }
|
|
func (InnerSchema) Name() string { return "Inner" }
|
|
|
|
// OffsetInner_ID is the byte offset of the ID field.
|
|
const OffsetInner_ID = 0
|
|
|
|
// OffsetInner_Label is the byte offset of the Label field.
|
|
const OffsetInner_Label = 8
|
|
|
|
// InnerSchemaFields is the namespace of every scalar field accessor for Inner.
|
|
// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.
|
|
// Byte-array fields are emitted as standalone functions, see below.
|
|
var InnerSchemaFields = struct {
|
|
ID zapv1.Field[InnerSchema, uint64]
|
|
}{
|
|
ID: zapv1.At[InnerSchema, uint64](0),
|
|
}
|
|
|
|
// NewInner builds a fresh Inner 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 NewInner(iD uint64, label string) (zapv1.View[InnerSchema], []byte) {
|
|
b := zap.NewBuilder(zap.HeaderSize + SizeInner + len(label))
|
|
ob := b.StartObject(SizeInner)
|
|
ob.SetUint64(OffsetInner_ID, iD)
|
|
ob.SetText(OffsetInner_Label, label)
|
|
rootOff := ob.FinishAsRoot()
|
|
buf := b.Finish()
|
|
end := rootOff + SizeInner
|
|
return zapv1.AsView[InnerSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
|
}
|
|
|
|
// WrapInner parses a ZAP buffer into a typed
|
|
// [zapv1.View[Inner]]. 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 WrapInner(b []byte) (zapv1.View[InnerSchema], error) {
|
|
msg, err := zap.Parse(b)
|
|
if err != nil {
|
|
return zapv1.View[InnerSchema]{}, err
|
|
}
|
|
root := msg.Root()
|
|
data := msg.Bytes()
|
|
rootOff := root.Offset()
|
|
end := rootOff + SizeInner
|
|
if end > len(data) {
|
|
end = len(data) // Read returns zero on OOB; v1 graceful degradation
|
|
}
|
|
return zapv1.AsView[InnerSchema](zapv1.RawFromSlices(data, rootOff, end)), nil
|
|
}
|
|
|
|
// InnerLabel reads the variable-length Label string field of Inner.
|
|
//
|
|
// Zero-copy: v1's Object.Text returns a string over a sub-slice of the
|
|
// underlying buffer. Valid only while the View's buffer is alive.
|
|
func InnerLabel(v zapv1.View[InnerSchema]) string {
|
|
msg := zap.WrapBuffer(v.Bytes())
|
|
obj := msg.RootObjectAt(int(zapv1.RootOff(v)))
|
|
return obj.Text(OffsetInner_Label)
|
|
}
|
|
|
|
func init() {
|
|
zapv1.Register[InnerSchema](zapv1.DefaultRegistry)
|
|
}
|