mirror of
https://github.com/luxfi/zap.git
synced 2026-10-30 15:04:16 +00:00
Completes the variable-length codegen (strings/bytes already shipped; lists now
join them). A list field of a fixed-size element schema generates: a per-element
value-input struct, a typed constructor param []Elem, an inline WriteList build
(bridged onto the hand-rolled ObjectBuilder by the new zapv1.SetterFrom, one
zapv1.Write per element field), and a zero-copy ListAt read accessor returning
zapv1.List[E] (range-over-func ready) — mechanically reproducing examples/
batch_tx.go.
Adds: Schema.Element (flat list-element slots carry no kind byte — fields may
start at offset 0; Wrap skips the kind check); runtime helpers SetterFrom /
WriteString / WriteBytes bridging the hand-rolled fast path to the typed writers.
Proven end-to-end: testpkg/listwire round-trips a BatchTx{scalar + []Item}
through build -> wrap -> ListAt.All() with every element read zero-copy
(TestRoundTrip_List), plus generator-output tests (valid Go via go/parser +
construct assertions). Existing golden tests unchanged.
114 lines
3.9 KiB
Go
114 lines
3.9 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: BatchTx (kind=0x21, size=17).
|
|
|
|
package listwire
|
|
|
|
import (
|
|
"github.com/luxfi/zap"
|
|
zapv1 "github.com/luxfi/zap/v1"
|
|
)
|
|
|
|
// KindBatchTx is the wire discriminator for BatchTx.
|
|
const KindBatchTx zapv1.KindByte = 0x21
|
|
|
|
// SizeBatchTx is the fixed object payload size in bytes.
|
|
const SizeBatchTx = 17
|
|
|
|
// BatchSchema is the v2 schema marker for BatchTx. Methods are constant-
|
|
// returning so concrete-typed [zapv1.Wrap[BatchSchema]] calls fold to
|
|
// literals at the call site.
|
|
type BatchSchema struct{}
|
|
|
|
func (BatchSchema) Kind() zapv1.KindByte { return KindBatchTx }
|
|
func (BatchSchema) Size() int { return SizeBatchTx }
|
|
func (BatchSchema) Name() string { return "BatchTx" }
|
|
|
|
// OffsetBatchTx_ID is the byte offset of the ID field.
|
|
const OffsetBatchTx_ID = 1
|
|
|
|
// OffsetBatchTx_Items is the byte offset of the Items field.
|
|
const OffsetBatchTx_Items = 9
|
|
|
|
// BatchSchemaFields is the namespace of every scalar field accessor for BatchTx.
|
|
// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.
|
|
// Byte-array fields are emitted as standalone functions, see below.
|
|
var BatchSchemaFields = struct {
|
|
ID zapv1.Field[BatchSchema, uint64]
|
|
}{
|
|
ID: zapv1.At[BatchSchema, uint64](1),
|
|
}
|
|
|
|
// NewBatchTx builds a fresh BatchTx 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 NewBatchTx(iD uint64, items []Item) (zapv1.View[BatchSchema], []byte) {
|
|
b := zap.NewBuilder(zap.HeaderSize + SizeBatchTx)
|
|
ob := b.StartObject(SizeBatchTx)
|
|
ob.SetUint8(0, uint8(KindBatchTx))
|
|
ob.SetUint64(OffsetBatchTx_ID, iD)
|
|
ls := zapv1.SetterFrom[BatchSchema](ob, b)
|
|
zapv1.WriteList[BatchSchema, ItemSchema](ls, OffsetBatchTx_Items, func(es *zapv1.ElemSetter[ItemSchema]) {
|
|
for _, it := range items {
|
|
es.Append(func(e zapv1.Setter[ItemSchema]) {
|
|
zapv1.Write(e, ItemSchemaFields.ID, it.ID)
|
|
zapv1.Write(e, ItemSchemaFields.Value, it.Value)
|
|
})
|
|
}
|
|
})
|
|
rootOff := ob.FinishAsRoot()
|
|
buf := b.Finish()
|
|
end := rootOff + SizeBatchTx
|
|
return zapv1.AsView[BatchSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
|
}
|
|
|
|
// WrapBatchTx parses a ZAP buffer into a typed
|
|
// [zapv1.View[BatchTx]]. 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 WrapBatchTx(b []byte) (zapv1.View[BatchSchema], error) {
|
|
msg, err := zap.Parse(b)
|
|
if err != nil {
|
|
return zapv1.View[BatchSchema]{}, err
|
|
}
|
|
root := msg.Root()
|
|
if got := root.Uint8(0); got != uint8(KindBatchTx) {
|
|
return zapv1.View[BatchSchema]{}, zapv1.NewSchemaError(
|
|
KindBatchTx, zapv1.KindByte(got), "BatchTx")
|
|
}
|
|
data := msg.Bytes()
|
|
rootOff := root.Offset()
|
|
end := rootOff + SizeBatchTx
|
|
if end > len(data) {
|
|
end = len(data) // Read returns zero on OOB; v1 graceful degradation
|
|
}
|
|
return zapv1.AsView[BatchSchema](zapv1.RawFromSlices(data, rootOff, end)), nil
|
|
}
|
|
|
|
// Item is the per-element input for the BatchTx.Items list.
|
|
type Item struct {
|
|
ID uint64
|
|
Value uint64
|
|
}
|
|
|
|
// BatchTxItems returns the variable-length Items list of BatchTx as a
|
|
// range-over-func-ready [zapv1.List][ItemSchema]. Zero-copy: each element view
|
|
// indexes straight into the underlying buffer.
|
|
//
|
|
// for it := range BatchTxItems(view).All() {
|
|
// // zapv1.Read(it, ItemSchemaFields.X)
|
|
// }
|
|
func BatchTxItems(v zapv1.View[BatchSchema]) zapv1.List[ItemSchema] {
|
|
return zapv1.ListAt[BatchSchema, ItemSchema](v, OffsetBatchTx_Items)
|
|
}
|