mirror of
https://github.com/luxfi/zap.git
synced 2026-07-26 22:53:31 +00:00
rename v2 -> v1: the typed-view API + codegen is the canonical 1.0 (no v2, ever)
There is one perfected typed ZAP layer and it lives at github.com/luxfi/zap/v1 — forwards-only, no backwards-compat baggage, never a breaking major. Mechanical, behavior-preserving: v2/ -> v1/ (git mv), package zapv2 -> zapv1, import path .../zap/v2 -> .../zap/v1 (incl. the codegen's emitted banner + import so generated files reference /v1). Codegen golden tests pass; typed layer vets clean. (Pre-existing CGO 'resolv' link failures in the root package are unrelated env noise.)
This commit is contained in:
+1
-1
@@ -282,7 +282,7 @@ func (ob *ObjectBuilder) ensureField(endOffset int) {
|
||||
// backwards).
|
||||
//
|
||||
// This is the exported counterpart to the internal ensureField helper.
|
||||
// It is used by zapv2.WriteList to keep the parent's payload reserved
|
||||
// It is used by zapv1.WriteList to keep the parent's payload reserved
|
||||
// before list elements are appended.
|
||||
func (ob *ObjectBuilder) ReserveFixed(dataSize int) {
|
||||
ob.ensureField(dataSize)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// which emits v1-equivalent fast paths from a declarative .zap source.
|
||||
//
|
||||
// Consumer dispatch for ad-hoc / dynamic schemas goes through the v2
|
||||
// generic API (github.com/luxfi/zap/v2).
|
||||
// generic API (github.com/luxfi/zap/v1).
|
||||
//
|
||||
// The v1 hand-rolled code in this package remains for in-flight
|
||||
// migration of legacy callers (luxfi/node/vms/platformvm/txs/zap_native,
|
||||
|
||||
+13
-13
@@ -13,8 +13,8 @@
|
||||
// Expected output (Go 1.23+):
|
||||
//
|
||||
// ./cross_schema_field.go:NN:NN: cannot use AlphaFields.X (variable
|
||||
// of type zapv2.Field[AlphaSchema, uint64]) as
|
||||
// zapv2.Field[BetaSchema, uint64] value in argument to zapv2.Read
|
||||
// of type zapv1.Field[AlphaSchema, uint64]) as
|
||||
// zapv1.Field[BetaSchema, uint64] value in argument to zapv1.Read
|
||||
//
|
||||
// The directory name begins with an underscore so `go build ./...`
|
||||
// at the v2 root skips it; only an explicit build path includes it,
|
||||
@@ -23,44 +23,44 @@
|
||||
package compile_fail_demo
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap/v2"
|
||||
"github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// AlphaSchema is one schema...
|
||||
type AlphaSchema struct{}
|
||||
|
||||
func (AlphaSchema) Kind() zapv2.KindByte { return 0xA1 }
|
||||
func (AlphaSchema) Kind() zapv1.KindByte { return 0xA1 }
|
||||
func (AlphaSchema) Size() int { return 16 }
|
||||
func (AlphaSchema) Name() string { return "Alpha" }
|
||||
|
||||
// BetaSchema is a different schema...
|
||||
type BetaSchema struct{}
|
||||
|
||||
func (BetaSchema) Kind() zapv2.KindByte { return 0xB1 }
|
||||
func (BetaSchema) Kind() zapv1.KindByte { return 0xB1 }
|
||||
func (BetaSchema) Size() int { return 16 }
|
||||
func (BetaSchema) Name() string { return "Beta" }
|
||||
|
||||
var (
|
||||
AlphaFields = struct {
|
||||
X zapv2.Field[AlphaSchema, uint64]
|
||||
}{X: zapv2.At[AlphaSchema, uint64](1)}
|
||||
X zapv1.Field[AlphaSchema, uint64]
|
||||
}{X: zapv1.At[AlphaSchema, uint64](1)}
|
||||
|
||||
BetaFields = struct {
|
||||
Y zapv2.Field[BetaSchema, uint64]
|
||||
}{Y: zapv2.At[BetaSchema, uint64](1)}
|
||||
Y zapv1.Field[BetaSchema, uint64]
|
||||
}{Y: zapv1.At[BetaSchema, uint64](1)}
|
||||
)
|
||||
|
||||
// crossSchemaRead is the load-bearing compile-time-safety
|
||||
// demonstration. The compiler MUST reject this because
|
||||
// AlphaFields.X is a Field[AlphaSchema, uint64] but the View is
|
||||
// View[BetaSchema] — the type parameters do not unify.
|
||||
func crossSchemaRead(beta zapv2.View[BetaSchema]) uint64 {
|
||||
return zapv2.Read(beta, AlphaFields.X) // COMPILE ERROR
|
||||
func crossSchemaRead(beta zapv1.View[BetaSchema]) uint64 {
|
||||
return zapv1.Read(beta, AlphaFields.X) // COMPILE ERROR
|
||||
}
|
||||
|
||||
// crossTypeWrite tries to write an int64 into a Field declared for
|
||||
// uint64. The compiler MUST reject this because the value type does
|
||||
// not match the field's T parameter.
|
||||
func crossTypeWrite(s zapv2.Setter[AlphaSchema]) {
|
||||
zapv2.Write(s, AlphaFields.X, int64(42)) // COMPILE ERROR
|
||||
func crossTypeWrite(s zapv1.Setter[AlphaSchema]) {
|
||||
zapv1.Write(s, AlphaFields.X, int64(42)) // COMPILE ERROR
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2_test
|
||||
package zapv1_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/zap"
|
||||
"github.com/luxfi/zap/v2"
|
||||
"github.com/luxfi/zap/v2/examples"
|
||||
"github.com/luxfi/zap/v1"
|
||||
"github.com/luxfi/zap/v1/examples"
|
||||
)
|
||||
|
||||
// Benchmark baseline reference:
|
||||
@@ -34,8 +34,8 @@ import (
|
||||
// changing the v2 API.
|
||||
|
||||
// BenchmarkGeneric_Build_AdvanceTime builds the canary AdvanceTimeTx
|
||||
// via the imperative-style v2 generic API ([zapv2.NewBuilderFor] +
|
||||
// [zapv2.WriteB] + Finish). Targets matching v1's 1-alloc profile.
|
||||
// via the imperative-style v2 generic API ([zapv1.NewBuilderFor] +
|
||||
// [zapv1.WriteB] + Finish). Targets matching v1's 1-alloc profile.
|
||||
func BenchmarkGeneric_Build_AdvanceTime(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -76,7 +76,7 @@ func BenchmarkGeneric_Read_AdvanceTime(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
v, _ := examples.WrapAdvanceTime(buf)
|
||||
_ = zapv2.Read(v, examples.AdvanceTimeFields.Time)
|
||||
_ = zapv1.Read(v, examples.AdvanceTimeFields.Time)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func BenchmarkGeneric_Read_NoParse(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
var sink uint64
|
||||
for i := 0; i < b.N; i++ {
|
||||
sink = zapv2.Read(view, examples.AdvanceTimeFields.Time)
|
||||
sink = zapv1.Read(view, examples.AdvanceTimeFields.Time)
|
||||
}
|
||||
_ = sink
|
||||
}
|
||||
@@ -152,7 +152,7 @@ func BenchmarkGeneric_List_Range(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var sum uint64
|
||||
for v := range list.All() {
|
||||
sum += zapv2.Read(v, examples.ItemFields.Value)
|
||||
sum += zapv1.Read(v, examples.ItemFields.Value)
|
||||
}
|
||||
_ = sum
|
||||
}
|
||||
@@ -175,7 +175,7 @@ func BenchmarkGeneric_List_Range_Payloads(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
var sum uint64
|
||||
for p := range list.Payloads() {
|
||||
sum += zapv2.ReadPayload(p, examples.ItemFields.Value)
|
||||
sum += zapv1.ReadPayload(p, examples.ItemFields.Value)
|
||||
}
|
||||
_ = sum
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func BenchmarkHandRolled_List_Range(b *testing.B) {
|
||||
// have zero allocations per Get/Put pair once it's warm.
|
||||
func BenchmarkPool_GetPut(b *testing.B) {
|
||||
type Box struct{ N uint64 }
|
||||
pool := zapv2.NewPool(func() *Box { return &Box{} })
|
||||
pool := zapv1.NewPool(func() *Box { return &Box{} })
|
||||
// Warm up the pool.
|
||||
for i := 0; i < 100; i++ {
|
||||
pool.Put(pool.Get())
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap"
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// bb := zapv2.NewBuilderFor[AdvanceTimeSchema]()
|
||||
// zapv2.WriteB(bb, examples.AdvanceTimeFields.Time, ts)
|
||||
// bb := zapv1.NewBuilderFor[AdvanceTimeSchema]()
|
||||
// zapv1.WriteB(bb, examples.AdvanceTimeFields.Time, ts)
|
||||
// view, buf := bb.Finish()
|
||||
//
|
||||
// WriteB is the explicit-receiver counterpart to [Write] — both take
|
||||
@@ -53,7 +53,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/luxfi/zap/v2/codegen"
|
||||
"github.com/luxfi/zap/v1/codegen"
|
||||
)
|
||||
|
||||
// schemaSpec is the JSON wire shape for a single schema. It is the
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/luxfi/zap/v2/codegen"
|
||||
"github.com/luxfi/zap/v1/codegen"
|
||||
)
|
||||
|
||||
type fieldFlag struct {
|
||||
@@ -12,7 +12,7 @@
|
||||
// into its caller, so the call site pays a function-call cost (~5-7
|
||||
// ns on modern hardware). The work performed by a "Wrap" function
|
||||
// (parse the ZAP wire frame, validate the kind discriminator, build
|
||||
// a typed view) exceeds that budget. The generic [zapv2.Wrap[S]]
|
||||
// a typed view) exceeds that budget. The generic [zapv1.Wrap[S]]
|
||||
// function therefore costs one function call per Wrap, even when
|
||||
// every other primitive in its body would inline.
|
||||
//
|
||||
@@ -32,7 +32,7 @@
|
||||
// For a schema declared as:
|
||||
//
|
||||
// type AdvanceTimeSchema struct{}
|
||||
// func (AdvanceTimeSchema) Kind() zapv2.KindByte { return 1 }
|
||||
// func (AdvanceTimeSchema) Kind() zapv1.KindByte { return 1 }
|
||||
// func (AdvanceTimeSchema) Size() int { return 9 }
|
||||
// func (AdvanceTimeSchema) Name() string { return "AdvanceTimeTx" }
|
||||
//
|
||||
@@ -44,7 +44,7 @@
|
||||
// const kindAdvanceTimeTx uint8 = 1
|
||||
// const offsetAdvanceTimeTx_Time = 1
|
||||
//
|
||||
// func WrapAdvanceTime(b []byte) (zapv2.View[AdvanceTimeSchema], error) {
|
||||
// func WrapAdvanceTime(b []byte) (zapv1.View[AdvanceTimeSchema], error) {
|
||||
// msg, err := zap.Parse(b)
|
||||
// ...
|
||||
// }
|
||||
@@ -61,8 +61,8 @@
|
||||
// file, a Cap'n-Proto-style schema file, struct tags) and want
|
||||
// ZAP v2 accessors emitted automatically.
|
||||
//
|
||||
// For cold paths and ad-hoc schemas, the generic [zapv2.Wrap[S]] /
|
||||
// [zapv2.Build[S]] are equally correct and one extra function call
|
||||
// For cold paths and ad-hoc schemas, the generic [zapv1.Wrap[S]] /
|
||||
// [zapv1.Build[S]] are equally correct and one extra function call
|
||||
// slower — which is rarely the bottleneck.
|
||||
//
|
||||
// # Status
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// typeToSize maps a [zapv2.FieldKind] Go type name to its byte width.
|
||||
// typeToSize maps a [zapv1.FieldKind] Go type name to its byte width.
|
||||
// Used by the field-write code to pick the right ObjectBuilder.Set*
|
||||
// method.
|
||||
var typeToSize = map[string]int{
|
||||
@@ -68,12 +68,12 @@ func fieldByteSize(f Field) (int, bool) {
|
||||
// v1 hand-rolled performance to within compiler noise — verified by
|
||||
// the bench suite.
|
||||
//
|
||||
// Scalar fields go through the [zapv2.Field][S, T] generic handle
|
||||
// Scalar fields go through the [zapv1.Field][S, T] generic handle
|
||||
// (declared in the per-schema <GoName>Fields var). Fixed-width
|
||||
// byte-array fields ("bytes<N>") are emitted as standalone typed
|
||||
// accessor functions that call v1's SetBytesFixed / BytesFixedSlice
|
||||
// — they do NOT appear in the Fields struct because [N]byte is not a
|
||||
// [zapv2.FieldKind] member. Both forms produce the same wire layout.
|
||||
// [zapv1.FieldKind] member. Both forms produce the same wire layout.
|
||||
func Emit(w io.Writer, s Schema) error {
|
||||
// Validate field types + offsets.
|
||||
for _, f := range s.Fields {
|
||||
@@ -109,21 +109,21 @@ func Emit(w io.Writer, s Schema) error {
|
||||
fmt.Fprintf(w, `// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
//
|
||||
// Code generated by github.com/luxfi/zap/v2/codegen — DO NOT EDIT.
|
||||
// Code generated by github.com/luxfi/zap/v1/codegen — DO NOT EDIT.
|
||||
// Source schema: %s (kind=0x%02x, size=%d).
|
||||
|
||||
package %s
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap"
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
`, s.WireName, s.Kind, s.Size, s.Package)
|
||||
|
||||
// Constants.
|
||||
fmt.Fprintf(w, `// Kind%s is the wire discriminator for %s.
|
||||
const Kind%s zapv2.KindByte = 0x%02x
|
||||
const Kind%s zapv1.KindByte = 0x%02x
|
||||
|
||||
// Size%s is the fixed object payload size in bytes.
|
||||
const Size%s = %d
|
||||
@@ -133,11 +133,11 @@ const Size%s = %d
|
||||
|
||||
// Schema marker type.
|
||||
fmt.Fprintf(w, `// %s is the v2 schema marker for %s. Methods are constant-
|
||||
// returning so concrete-typed [zapv2.Wrap[%s]] calls fold to
|
||||
// returning so concrete-typed [zapv1.Wrap[%s]] calls fold to
|
||||
// literals at the call site.
|
||||
type %s struct{}
|
||||
|
||||
func (%s) Kind() zapv2.KindByte { return Kind%s }
|
||||
func (%s) Kind() zapv1.KindByte { return Kind%s }
|
||||
func (%s) Size() int { return Size%s }
|
||||
func (%s) Name() string { return %q }
|
||||
|
||||
@@ -157,10 +157,10 @@ func (%s) Name() string { return %q }
|
||||
// Byte-array fields are handled by standalone accessor functions
|
||||
// (emitted after the constructor) because [N]byte is not a
|
||||
// FieldKind union member.
|
||||
// Scalar fields go in the Fields struct (zapv2.Field handles).
|
||||
// Scalar fields go in the Fields struct (zapv1.Field handles).
|
||||
// Fixed byte-arrays and variable-length tails (string/bytes) get
|
||||
// standalone typed accessors instead — neither [N]byte nor string/
|
||||
// []byte is a zapv2.FieldKind member.
|
||||
// []byte is a zapv1.FieldKind member.
|
||||
var scalarFields []Field
|
||||
var accessorFields []Field
|
||||
for _, f := range s.Fields {
|
||||
@@ -174,15 +174,15 @@ func (%s) Name() string { return %q }
|
||||
if len(scalarFields) > 0 {
|
||||
fmt.Fprintf(w, "// %sFields is the namespace of every scalar field accessor for %s.\n",
|
||||
s.GoName, s.WireName)
|
||||
fmt.Fprintf(w, "// Use with [zapv2.Read] / [zapv2.Write] for type-safe access.\n")
|
||||
fmt.Fprintf(w, "// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.\n")
|
||||
fmt.Fprintf(w, "// Byte-array fields are emitted as standalone functions, see below.\nvar %sFields = struct {\n",
|
||||
s.GoName)
|
||||
for _, f := range scalarFields {
|
||||
fmt.Fprintf(w, "\t%s zapv2.Field[%s, %s]\n", f.Name, s.GoName, f.Type)
|
||||
fmt.Fprintf(w, "\t%s zapv1.Field[%s, %s]\n", f.Name, s.GoName, f.Type)
|
||||
}
|
||||
fmt.Fprintf(w, "}{\n")
|
||||
for _, f := range scalarFields {
|
||||
fmt.Fprintf(w, "\t%s: zapv2.At[%s, %s](%d),\n",
|
||||
fmt.Fprintf(w, "\t%s: zapv1.At[%s, %s](%d),\n",
|
||||
f.Name, s.GoName, f.Type, f.Offset)
|
||||
}
|
||||
fmt.Fprintf(w, "}\n\n")
|
||||
@@ -244,7 +244,7 @@ func emitNewConstructor(w io.Writer, s Schema, scalar, accessor []Field) {
|
||||
// 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 New%s(%s) (zapv2.View[%s], []byte) {
|
||||
func New%s(%s) (zapv1.View[%s], []byte) {
|
||||
b := zap.NewBuilder(%s)
|
||||
ob := b.StartObject(Size%s)
|
||||
ob.SetUint8(0, uint8(Kind%s))
|
||||
@@ -273,7 +273,7 @@ func New%s(%s) (zapv2.View[%s], []byte) {
|
||||
fmt.Fprintf(w, ` rootOff := ob.FinishAsRoot()
|
||||
buf := b.Finish()
|
||||
end := rootOff + Size%s
|
||||
return zapv2.AsView[%s](zapv2.RawFromSlices(buf, rootOff, end)), buf
|
||||
return zapv1.AsView[%s](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
||||
}
|
||||
|
||||
`, s.WireName, s.GoName)
|
||||
@@ -283,22 +283,22 @@ func New%s(%s) (zapv2.View[%s], []byte) {
|
||||
// type-checks a buffer. The body uses v1 primitives so it inlines.
|
||||
func emitWrapFunction(w io.Writer, s Schema) {
|
||||
fmt.Fprintf(w, `// Wrap%s parses a ZAP buffer into a typed
|
||||
// [zapv2.View[%s]]. Validates the wire frame and the kind
|
||||
// discriminator at offset 0; returns [*zapv2.SchemaError] on kind
|
||||
// [zapv1.View[%s]]. 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 Wrap%s(b []byte) (zapv2.View[%s], error) {
|
||||
func Wrap%s(b []byte) (zapv1.View[%s], error) {
|
||||
msg, err := zap.Parse(b)
|
||||
if err != nil {
|
||||
return zapv2.View[%s]{}, err
|
||||
return zapv1.View[%s]{}, err
|
||||
}
|
||||
root := msg.Root()
|
||||
if got := root.Uint8(0); got != uint8(Kind%s) {
|
||||
return zapv2.View[%s]{}, zapv2.NewSchemaError(
|
||||
Kind%s, zapv2.KindByte(got), %q)
|
||||
return zapv1.View[%s]{}, zapv1.NewSchemaError(
|
||||
Kind%s, zapv1.KindByte(got), %q)
|
||||
}
|
||||
data := msg.Bytes()
|
||||
rootOff := root.Offset()
|
||||
@@ -306,7 +306,7 @@ func Wrap%s(b []byte) (zapv2.View[%s], error) {
|
||||
if end > len(data) {
|
||||
end = len(data) // Read returns zero on OOB; v1 graceful degradation
|
||||
}
|
||||
return zapv2.AsView[%s](zapv2.RawFromSlices(data, rootOff, end)), nil
|
||||
return zapv1.AsView[%s](zapv1.RawFromSlices(data, rootOff, end)), nil
|
||||
}
|
||||
|
||||
`, s.WireName, s.WireName,
|
||||
@@ -335,9 +335,9 @@ func emitAccessorFields(w io.Writer, s Schema, fields []Field) {
|
||||
//
|
||||
// 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 %s%s(v zapv2.View[%s]) string {
|
||||
func %s%s(v zapv1.View[%s]) string {
|
||||
msg := zap.WrapBuffer(v.Bytes())
|
||||
obj := msg.RootObjectAt(int(zapv2.RootOff(v)))
|
||||
obj := msg.RootObjectAt(int(zapv1.RootOff(v)))
|
||||
return obj.Text(Offset%s_%s)
|
||||
}
|
||||
|
||||
@@ -349,9 +349,9 @@ func %s%s(v zapv2.View[%s]) string {
|
||||
//
|
||||
// Zero-copy: v1's Object.Bytes returns a sub-slice of the underlying
|
||||
// buffer. Valid only while the View's buffer is alive; copy to retain.
|
||||
func %s%s(v zapv2.View[%s]) []byte {
|
||||
func %s%s(v zapv1.View[%s]) []byte {
|
||||
msg := zap.WrapBuffer(v.Bytes())
|
||||
obj := msg.RootObjectAt(int(zapv2.RootOff(v)))
|
||||
obj := msg.RootObjectAt(int(zapv1.RootOff(v)))
|
||||
return obj.Bytes(Offset%s_%s)
|
||||
}
|
||||
|
||||
@@ -366,9 +366,9 @@ func %s%s(v zapv2.View[%s]) []byte {
|
||||
// a sub-slice of the underlying buffer); the returned [%d]byte is a
|
||||
// value copy so the caller's slot owns the bytes after the View's
|
||||
// buffer is freed.
|
||||
func %s%s(v zapv2.View[%s]) [%d]byte {
|
||||
func %s%s(v zapv1.View[%s]) [%d]byte {
|
||||
msg := zap.WrapBuffer(v.Bytes())
|
||||
obj := msg.RootObjectAt(int(zapv2.RootOff(v)))
|
||||
obj := msg.RootObjectAt(int(zapv1.RootOff(v)))
|
||||
slice := obj.BytesFixedSlice(Offset%s_%s, %d)
|
||||
var out [%d]byte
|
||||
if len(slice) == %d {
|
||||
@@ -388,7 +388,7 @@ func %s%s(v zapv2.View[%s]) [%d]byte {
|
||||
}
|
||||
|
||||
// emitRegisterInit writes an init function that registers the schema
|
||||
// with the [zapv2.DefaultRegistry]. Skipped when [Schema.SkipRegistry]
|
||||
// with the [zapv1.DefaultRegistry]. Skipped when [Schema.SkipRegistry]
|
||||
// is true, used for schemas whose Kind byte is local to a per-package
|
||||
// (private) registry rather than globally unique.
|
||||
func emitRegisterInit(w io.Writer, s Schema) {
|
||||
@@ -396,7 +396,7 @@ func emitRegisterInit(w io.Writer, s Schema) {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, `func init() {
|
||||
zapv2.Register[%s](zapv2.DefaultRegistry)
|
||||
zapv1.Register[%s](zapv1.DefaultRegistry)
|
||||
}
|
||||
`, s.GoName)
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/zap/v2/codegen"
|
||||
"github.com/luxfi/zap/v1/codegen"
|
||||
)
|
||||
|
||||
// TestEmit_AdvanceTime: the canary schema emits source that compiles
|
||||
@@ -40,12 +40,12 @@ func TestEmit_AdvanceTime(t *testing.T) {
|
||||
// Load-bearing markers — the things downstream code uses.
|
||||
wants := []string{
|
||||
"package examples",
|
||||
"KindAdvanceTimeTx zapv2.KindByte = 0x01",
|
||||
"KindAdvanceTimeTx zapv1.KindByte = 0x01",
|
||||
"SizeAdvanceTimeTx = 9",
|
||||
"type AdvanceTimeSchema struct{}",
|
||||
"OffsetAdvanceTimeTx_Time = 1",
|
||||
"AdvanceTimeSchemaFields",
|
||||
"Time zapv2.Field[AdvanceTimeSchema, uint64]",
|
||||
"Time zapv1.Field[AdvanceTimeSchema, uint64]",
|
||||
"func NewAdvanceTimeTx(time uint64)",
|
||||
"func WrapAdvanceTimeTx(b []byte)",
|
||||
"zap.NewBuilder(zap.HeaderSize + SizeAdvanceTimeTx)",
|
||||
@@ -54,9 +54,9 @@ func TestEmit_AdvanceTime(t *testing.T) {
|
||||
"zap.Parse(b)",
|
||||
"msg.Root()",
|
||||
"root.Uint8(0)",
|
||||
"zapv2.AsView[AdvanceTimeSchema]",
|
||||
"zapv2.RawFromSlices",
|
||||
"zapv2.Register[AdvanceTimeSchema](zapv2.DefaultRegistry)",
|
||||
"zapv1.AsView[AdvanceTimeSchema]",
|
||||
"zapv1.RawFromSlices",
|
||||
"zapv1.Register[AdvanceTimeSchema](zapv1.DefaultRegistry)",
|
||||
}
|
||||
for _, want := range wants {
|
||||
if !strings.Contains(out, want) {
|
||||
@@ -117,9 +117,9 @@ func TestEmit_VarLength(t *testing.T) {
|
||||
"zap.HeaderSize + SizeVarTx + len(name) + len(data)", // buffer estimate
|
||||
"ob.SetText(OffsetVarTx_Name, name)",
|
||||
"ob.SetBytes(OffsetVarTx_Data, data)",
|
||||
"func VarTxName(v zapv2.View[VarSchema]) string",
|
||||
"func VarTxName(v zapv1.View[VarSchema]) string",
|
||||
"return obj.Text(OffsetVarTx_Name)",
|
||||
"func VarTxData(v zapv2.View[VarSchema]) []byte",
|
||||
"func VarTxData(v zapv1.View[VarSchema]) []byte",
|
||||
"return obj.Bytes(OffsetVarTx_Data)",
|
||||
}
|
||||
for _, want := range wants {
|
||||
@@ -128,7 +128,7 @@ func TestEmit_VarLength(t *testing.T) {
|
||||
}
|
||||
}
|
||||
// Variable fields must NOT appear in the scalar Fields struct.
|
||||
if strings.Contains(out, "Name zapv2.Field[") || strings.Contains(out, "Data zapv2.Field[") {
|
||||
if strings.Contains(out, "Name zapv1.Field[") || strings.Contains(out, "Data zapv1.Field[") {
|
||||
t.Errorf("variable fields must not be in the scalar Fields struct")
|
||||
}
|
||||
}
|
||||
@@ -155,14 +155,14 @@ func TestEmit_BytesField(t *testing.T) {
|
||||
}
|
||||
out := buf.String()
|
||||
wants := []string{
|
||||
"KindBlockRequest zapv2.KindByte = 0x53",
|
||||
"KindBlockRequest zapv1.KindByte = 0x53",
|
||||
"SizeBlockRequest = 34",
|
||||
"OffsetBlockRequest_Version = 1",
|
||||
"OffsetBlockRequest_BlockID = 2",
|
||||
// Scalar field in Fields struct
|
||||
"Version zapv2.Field[BlockReqSchema, uint8]",
|
||||
"Version zapv1.Field[BlockReqSchema, uint8]",
|
||||
// Byte-array field NOT in Fields struct, instead its own function:
|
||||
"func BlockRequestBlockID(v zapv2.View[BlockReqSchema]) [32]byte",
|
||||
"func BlockRequestBlockID(v zapv1.View[BlockReqSchema]) [32]byte",
|
||||
// Constructor takes both scalar and byte-array args
|
||||
"func NewBlockRequest(version uint8, blockID [32]byte)",
|
||||
// Constructor body writes both
|
||||
@@ -246,9 +246,9 @@ func TestEmit_MultiField(t *testing.T) {
|
||||
}
|
||||
out := buf.String()
|
||||
wants := []string{
|
||||
"KindBatchTx zapv2.KindByte = 0x21",
|
||||
"Flag zapv2.Field[BatchSchema, bool]",
|
||||
"ID zapv2.Field[BatchSchema, uint64]",
|
||||
"KindBatchTx zapv1.KindByte = 0x21",
|
||||
"Flag zapv1.Field[BatchSchema, bool]",
|
||||
"ID zapv1.Field[BatchSchema, uint64]",
|
||||
"OffsetBatchTx_Flag = 1",
|
||||
"OffsetBatchTx_ID = 9",
|
||||
"ob.SetBool(OffsetBatchTx_Flag, flag)",
|
||||
@@ -27,10 +27,10 @@ type Schema struct {
|
||||
// ("bytes<N>"), and variable-length tails ("string"/"bytes"). Each
|
||||
// occupies a slot in the fixed payload (variable-length fields hold
|
||||
// an 8-byte tail pointer there). List and nested-object tails are
|
||||
// not declared here; they use the generic [zapv2.ListAt] machinery.
|
||||
// not declared here; they use the generic [zapv1.ListAt] machinery.
|
||||
Fields []Field
|
||||
// SkipRegistry suppresses the emit of `init() { zapv2.Register[S]
|
||||
// (zapv2.DefaultRegistry) }`. Use for schema families that have a
|
||||
// SkipRegistry suppresses the emit of `init() { zapv1.Register[S]
|
||||
// (zapv1.DefaultRegistry) }`. Use for schema families that have a
|
||||
// PRIVATE Kind namespace (the discriminator byte is unique only
|
||||
// within a per-package registry, not globally). Examples:
|
||||
//
|
||||
@@ -40,7 +40,7 @@ type Schema struct {
|
||||
// would panic on duplicate kind byte at init time.
|
||||
// - LP-182 consensus wire: the 0x01..0x0D kind bytes are local to
|
||||
// the consensus-wire registry (`pkg/wire/zap/schemas.go`), not
|
||||
// the global zapv2.DefaultRegistry shared with P2P/light-client
|
||||
// the global zapv1.DefaultRegistry shared with P2P/light-client
|
||||
// schemas at 0xD0+/0xF0+.
|
||||
//
|
||||
// Default is false — schemas with globally-unique Kind bytes
|
||||
@@ -52,18 +52,18 @@ type Schema struct {
|
||||
//
|
||||
// Two field kinds are supported:
|
||||
//
|
||||
// 1. Scalar fields. Type is one of the [zapv2.FieldKind] members
|
||||
// 1. Scalar fields. Type is one of the [zapv1.FieldKind] members
|
||||
// (bool, int8/16/32/64, uint8/16/32/64, float32/64). The emitted
|
||||
// code uses a [zapv2.Field][S, T] handle and the standard
|
||||
// zapv2.Read/Write generic functions.
|
||||
// code uses a [zapv1.Field][S, T] handle and the standard
|
||||
// zapv1.Read/Write generic functions.
|
||||
//
|
||||
// 2. Fixed-width byte-array fields. Type is "bytes<N>" where N is a
|
||||
// positive integer (e.g., "bytes20" for NodeID, "bytes32" for
|
||||
// hashes, "bytes16" for session IDs). The emitted code uses the
|
||||
// v1 ObjectBuilder.SetBytesFixed / Object.BytesFixedSlice
|
||||
// accessors and returns the value as a [N]byte. Byte-array fields
|
||||
// do NOT use the zapv2.Field generic handle because [N]byte is
|
||||
// not a [zapv2.FieldKind] member; instead they get a typed
|
||||
// do NOT use the zapv1.Field generic handle because [N]byte is
|
||||
// not a [zapv1.FieldKind] member; instead they get a typed
|
||||
// accessor function emitted alongside the schema.
|
||||
//
|
||||
// 3. Variable-length tail fields. Type is "string" or "bytes" (no
|
||||
@@ -73,11 +73,11 @@ type Schema struct {
|
||||
// ObjectBuilder.SetText / SetBytes; reads go through a standalone
|
||||
// accessor over v1's Object.Text / Object.Bytes (zero-copy
|
||||
// sub-slice of the buffer). Like byte-array fields, they do NOT use
|
||||
// the zapv2.Field generic handle (string/[]byte are not FieldKind
|
||||
// the zapv1.Field generic handle (string/[]byte are not FieldKind
|
||||
// members).
|
||||
//
|
||||
// List and nested-object tail fields are still hand-written (the
|
||||
// generic [zapv2.ListAt] / out-of-line pointer machinery).
|
||||
// generic [zapv1.ListAt] / out-of-line pointer machinery).
|
||||
type Field struct {
|
||||
// Name is the Go-visible field name (e.g. "Time"). Emitted into
|
||||
// the schema's Fields struct as `<SchemaGoName>Fields.Name`.
|
||||
@@ -129,5 +129,5 @@ func (f Field) IsVarBytes() bool { return f.Type == "bytes" }
|
||||
// IsVariable reports whether the field is any variable-length tail field
|
||||
// (string or bytes). Variable fields are emitted as standalone accessor
|
||||
// functions (like fixed byte arrays) rather than in the Fields struct,
|
||||
// because string/[]byte are not zapv2.FieldKind members.
|
||||
// because string/[]byte are not zapv1.FieldKind members.
|
||||
func (f Field) IsVariable() bool { return f.IsVarString() || f.IsVarBytes() }
|
||||
+28
-28
@@ -1,28 +1,28 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
//
|
||||
// Code generated by github.com/luxfi/zap/v2/codegen — DO NOT EDIT.
|
||||
// Code generated by github.com/luxfi/zap/v1/codegen — DO NOT EDIT.
|
||||
// Source schema: LightClientBlockHeaderRequest (kind=0x50, size=51).
|
||||
|
||||
package lcwire
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap"
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// KindLightClientBlockHeaderRequest is the wire discriminator for LightClientBlockHeaderRequest.
|
||||
const KindLightClientBlockHeaderRequest zapv2.KindByte = 0x50
|
||||
const KindLightClientBlockHeaderRequest zapv1.KindByte = 0x50
|
||||
|
||||
// SizeLightClientBlockHeaderRequest is the fixed object payload size in bytes.
|
||||
const SizeLightClientBlockHeaderRequest = 51
|
||||
|
||||
// LCBlockHeaderReqSchema is the v2 schema marker for LightClientBlockHeaderRequest. Methods are constant-
|
||||
// returning so concrete-typed [zapv2.Wrap[LCBlockHeaderReqSchema]] calls fold to
|
||||
// returning so concrete-typed [zapv1.Wrap[LCBlockHeaderReqSchema]] calls fold to
|
||||
// literals at the call site.
|
||||
type LCBlockHeaderReqSchema struct{}
|
||||
|
||||
func (LCBlockHeaderReqSchema) Kind() zapv2.KindByte { return KindLightClientBlockHeaderRequest }
|
||||
func (LCBlockHeaderReqSchema) Kind() zapv1.KindByte { return KindLightClientBlockHeaderRequest }
|
||||
func (LCBlockHeaderReqSchema) Size() int { return SizeLightClientBlockHeaderRequest }
|
||||
func (LCBlockHeaderReqSchema) Name() string { return "LightClientBlockHeaderRequest" }
|
||||
|
||||
@@ -45,20 +45,20 @@ const OffsetLightClientBlockHeaderRequest_CertMinTier = 46
|
||||
const OffsetLightClientBlockHeaderRequest_RequestID = 47
|
||||
|
||||
// LCBlockHeaderReqSchemaFields is the namespace of every scalar field accessor for LightClientBlockHeaderRequest.
|
||||
// Use with [zapv2.Read] / [zapv2.Write] for type-safe access.
|
||||
// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.
|
||||
// Byte-array fields are emitted as standalone functions, see below.
|
||||
var LCBlockHeaderReqSchemaFields = struct {
|
||||
Version zapv2.Field[LCBlockHeaderReqSchema, uint8]
|
||||
ChainID zapv2.Field[LCBlockHeaderReqSchema, uint32]
|
||||
BlockHeight zapv2.Field[LCBlockHeaderReqSchema, uint64]
|
||||
CertMinTier zapv2.Field[LCBlockHeaderReqSchema, uint8]
|
||||
RequestID zapv2.Field[LCBlockHeaderReqSchema, uint32]
|
||||
Version zapv1.Field[LCBlockHeaderReqSchema, uint8]
|
||||
ChainID zapv1.Field[LCBlockHeaderReqSchema, uint32]
|
||||
BlockHeight zapv1.Field[LCBlockHeaderReqSchema, uint64]
|
||||
CertMinTier zapv1.Field[LCBlockHeaderReqSchema, uint8]
|
||||
RequestID zapv1.Field[LCBlockHeaderReqSchema, uint32]
|
||||
}{
|
||||
Version: zapv2.At[LCBlockHeaderReqSchema, uint8](1),
|
||||
ChainID: zapv2.At[LCBlockHeaderReqSchema, uint32](2),
|
||||
BlockHeight: zapv2.At[LCBlockHeaderReqSchema, uint64](6),
|
||||
CertMinTier: zapv2.At[LCBlockHeaderReqSchema, uint8](46),
|
||||
RequestID: zapv2.At[LCBlockHeaderReqSchema, uint32](47),
|
||||
Version: zapv1.At[LCBlockHeaderReqSchema, uint8](1),
|
||||
ChainID: zapv1.At[LCBlockHeaderReqSchema, uint32](2),
|
||||
BlockHeight: zapv1.At[LCBlockHeaderReqSchema, uint64](6),
|
||||
CertMinTier: zapv1.At[LCBlockHeaderReqSchema, uint8](46),
|
||||
RequestID: zapv1.At[LCBlockHeaderReqSchema, uint32](47),
|
||||
}
|
||||
|
||||
// NewLightClientBlockHeaderRequest builds a fresh LightClientBlockHeaderRequest in a ZAP buffer.
|
||||
@@ -67,7 +67,7 @@ var LCBlockHeaderReqSchemaFields = struct {
|
||||
// [*Builder.StartObject], [*ObjectBuilder.Set*], [*Builder.Finish])
|
||||
// so the entire build expands at the call site. Result: 1 heap
|
||||
// alloc (the buffer), zero overhead vs v1.
|
||||
func NewLightClientBlockHeaderRequest(version uint8, chainID uint32, blockHeight uint64, certMinTier uint8, requestID uint32, blockContentHash [32]byte) (zapv2.View[LCBlockHeaderReqSchema], []byte) {
|
||||
func NewLightClientBlockHeaderRequest(version uint8, chainID uint32, blockHeight uint64, certMinTier uint8, requestID uint32, blockContentHash [32]byte) (zapv1.View[LCBlockHeaderReqSchema], []byte) {
|
||||
b := zap.NewBuilder(zap.HeaderSize + SizeLightClientBlockHeaderRequest)
|
||||
ob := b.StartObject(SizeLightClientBlockHeaderRequest)
|
||||
ob.SetUint8(0, uint8(KindLightClientBlockHeaderRequest))
|
||||
@@ -80,26 +80,26 @@ func NewLightClientBlockHeaderRequest(version uint8, chainID uint32, blockHeight
|
||||
rootOff := ob.FinishAsRoot()
|
||||
buf := b.Finish()
|
||||
end := rootOff + SizeLightClientBlockHeaderRequest
|
||||
return zapv2.AsView[LCBlockHeaderReqSchema](zapv2.RawFromSlices(buf, rootOff, end)), buf
|
||||
return zapv1.AsView[LCBlockHeaderReqSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
||||
}
|
||||
|
||||
// WrapLightClientBlockHeaderRequest parses a ZAP buffer into a typed
|
||||
// [zapv2.View[LightClientBlockHeaderRequest]]. Validates the wire frame and the kind
|
||||
// discriminator at offset 0; returns [*zapv2.SchemaError] on kind
|
||||
// [zapv1.View[LightClientBlockHeaderRequest]]. 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 WrapLightClientBlockHeaderRequest(b []byte) (zapv2.View[LCBlockHeaderReqSchema], error) {
|
||||
func WrapLightClientBlockHeaderRequest(b []byte) (zapv1.View[LCBlockHeaderReqSchema], error) {
|
||||
msg, err := zap.Parse(b)
|
||||
if err != nil {
|
||||
return zapv2.View[LCBlockHeaderReqSchema]{}, err
|
||||
return zapv1.View[LCBlockHeaderReqSchema]{}, err
|
||||
}
|
||||
root := msg.Root()
|
||||
if got := root.Uint8(0); got != uint8(KindLightClientBlockHeaderRequest) {
|
||||
return zapv2.View[LCBlockHeaderReqSchema]{}, zapv2.NewSchemaError(
|
||||
KindLightClientBlockHeaderRequest, zapv2.KindByte(got), "LightClientBlockHeaderRequest")
|
||||
return zapv1.View[LCBlockHeaderReqSchema]{}, zapv1.NewSchemaError(
|
||||
KindLightClientBlockHeaderRequest, zapv1.KindByte(got), "LightClientBlockHeaderRequest")
|
||||
}
|
||||
data := msg.Bytes()
|
||||
rootOff := root.Offset()
|
||||
@@ -107,7 +107,7 @@ func WrapLightClientBlockHeaderRequest(b []byte) (zapv2.View[LCBlockHeaderReqSch
|
||||
if end > len(data) {
|
||||
end = len(data) // Read returns zero on OOB; v1 graceful degradation
|
||||
}
|
||||
return zapv2.AsView[LCBlockHeaderReqSchema](zapv2.RawFromSlices(data, rootOff, end)), nil
|
||||
return zapv1.AsView[LCBlockHeaderReqSchema](zapv1.RawFromSlices(data, rootOff, end)), nil
|
||||
}
|
||||
|
||||
// LightClientBlockHeaderRequestBlockContentHash reads the 32-byte inline BlockContentHash field of LightClientBlockHeaderRequest.
|
||||
@@ -116,9 +116,9 @@ func WrapLightClientBlockHeaderRequest(b []byte) (zapv2.View[LCBlockHeaderReqSch
|
||||
// a sub-slice of the underlying buffer); the returned [32]byte is a
|
||||
// value copy so the caller's slot owns the bytes after the View's
|
||||
// buffer is freed.
|
||||
func LightClientBlockHeaderRequestBlockContentHash(v zapv2.View[LCBlockHeaderReqSchema]) [32]byte {
|
||||
func LightClientBlockHeaderRequestBlockContentHash(v zapv1.View[LCBlockHeaderReqSchema]) [32]byte {
|
||||
msg := zap.WrapBuffer(v.Bytes())
|
||||
obj := msg.RootObjectAt(int(zapv2.RootOff(v)))
|
||||
obj := msg.RootObjectAt(int(zapv1.RootOff(v)))
|
||||
slice := obj.BytesFixedSlice(OffsetLightClientBlockHeaderRequest_BlockContentHash, 32)
|
||||
var out [32]byte
|
||||
if len(slice) == 32 {
|
||||
@@ -128,5 +128,5 @@ func LightClientBlockHeaderRequestBlockContentHash(v zapv2.View[LCBlockHeaderReq
|
||||
}
|
||||
|
||||
func init() {
|
||||
zapv2.Register[LCBlockHeaderReqSchema](zapv2.DefaultRegistry)
|
||||
zapv1.Register[LCBlockHeaderReqSchema](zapv1.DefaultRegistry)
|
||||
}
|
||||
+3
-3
@@ -6,7 +6,7 @@ package consensuswire
|
||||
import (
|
||||
"testing"
|
||||
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// BenchmarkQuasarCert_Build measures the codegen-emitted NewQuasarCert
|
||||
@@ -61,7 +61,7 @@ func BenchmarkQuasarCert_RoundTrip(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatalf("Wrap: %v", err)
|
||||
}
|
||||
_ = zapv2.Read(view, QuasarCertSchemaFields.Epoch)
|
||||
_ = zapv1.Read(view, QuasarCertSchemaFields.Epoch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,6 @@ func BenchmarkQuasarCert_Read(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = zapv2.Read(view, QuasarCertSchemaFields.Epoch)
|
||||
_ = zapv1.Read(view, QuasarCertSchemaFields.Epoch)
|
||||
}
|
||||
}
|
||||
+41
-41
@@ -1,28 +1,28 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
//
|
||||
// Code generated by github.com/luxfi/zap/v2/codegen — DO NOT EDIT.
|
||||
// Code generated by github.com/luxfi/zap/v1/codegen — DO NOT EDIT.
|
||||
// Source schema: QuasarCert (kind=0x01, size=72).
|
||||
|
||||
package consensuswire
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap"
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// KindQuasarCert is the wire discriminator for QuasarCert.
|
||||
const KindQuasarCert zapv2.KindByte = 0x01
|
||||
const KindQuasarCert zapv1.KindByte = 0x01
|
||||
|
||||
// SizeQuasarCert is the fixed object payload size in bytes.
|
||||
const SizeQuasarCert = 72
|
||||
|
||||
// QuasarCertSchema is the v2 schema marker for QuasarCert. Methods are constant-
|
||||
// returning so concrete-typed [zapv2.Wrap[QuasarCertSchema]] calls fold to
|
||||
// returning so concrete-typed [zapv1.Wrap[QuasarCertSchema]] calls fold to
|
||||
// literals at the call site.
|
||||
type QuasarCertSchema struct{}
|
||||
|
||||
func (QuasarCertSchema) Kind() zapv2.KindByte { return KindQuasarCert }
|
||||
func (QuasarCertSchema) Kind() zapv1.KindByte { return KindQuasarCert }
|
||||
func (QuasarCertSchema) Size() int { return SizeQuasarCert }
|
||||
func (QuasarCertSchema) Name() string { return "QuasarCert" }
|
||||
|
||||
@@ -66,36 +66,36 @@ const OffsetQuasarCert_MLDSARollupOff = 64
|
||||
const OffsetQuasarCert_MLDSARollupLen = 68
|
||||
|
||||
// QuasarCertSchemaFields is the namespace of every scalar field accessor for QuasarCert.
|
||||
// Use with [zapv2.Read] / [zapv2.Write] for type-safe access.
|
||||
// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.
|
||||
// Byte-array fields are emitted as standalone functions, see below.
|
||||
var QuasarCertSchemaFields = struct {
|
||||
Epoch zapv2.Field[QuasarCertSchema, uint64]
|
||||
FinalityUnixNano zapv2.Field[QuasarCertSchema, int64]
|
||||
Validators zapv2.Field[QuasarCertSchema, uint32]
|
||||
BLSOff zapv2.Field[QuasarCertSchema, uint32]
|
||||
BLSLen zapv2.Field[QuasarCertSchema, uint32]
|
||||
CoronaOff zapv2.Field[QuasarCertSchema, uint32]
|
||||
CoronaLen zapv2.Field[QuasarCertSchema, uint32]
|
||||
PulsarOff zapv2.Field[QuasarCertSchema, uint32]
|
||||
PulsarLen zapv2.Field[QuasarCertSchema, uint32]
|
||||
MagnetarOff zapv2.Field[QuasarCertSchema, uint32]
|
||||
MagnetarLen zapv2.Field[QuasarCertSchema, uint32]
|
||||
MLDSARollupOff zapv2.Field[QuasarCertSchema, uint32]
|
||||
MLDSARollupLen zapv2.Field[QuasarCertSchema, uint32]
|
||||
Epoch zapv1.Field[QuasarCertSchema, uint64]
|
||||
FinalityUnixNano zapv1.Field[QuasarCertSchema, int64]
|
||||
Validators zapv1.Field[QuasarCertSchema, uint32]
|
||||
BLSOff zapv1.Field[QuasarCertSchema, uint32]
|
||||
BLSLen zapv1.Field[QuasarCertSchema, uint32]
|
||||
CoronaOff zapv1.Field[QuasarCertSchema, uint32]
|
||||
CoronaLen zapv1.Field[QuasarCertSchema, uint32]
|
||||
PulsarOff zapv1.Field[QuasarCertSchema, uint32]
|
||||
PulsarLen zapv1.Field[QuasarCertSchema, uint32]
|
||||
MagnetarOff zapv1.Field[QuasarCertSchema, uint32]
|
||||
MagnetarLen zapv1.Field[QuasarCertSchema, uint32]
|
||||
MLDSARollupOff zapv1.Field[QuasarCertSchema, uint32]
|
||||
MLDSARollupLen zapv1.Field[QuasarCertSchema, uint32]
|
||||
}{
|
||||
Epoch: zapv2.At[QuasarCertSchema, uint64](8),
|
||||
FinalityUnixNano: zapv2.At[QuasarCertSchema, int64](16),
|
||||
Validators: zapv2.At[QuasarCertSchema, uint32](24),
|
||||
BLSOff: zapv2.At[QuasarCertSchema, uint32](32),
|
||||
BLSLen: zapv2.At[QuasarCertSchema, uint32](36),
|
||||
CoronaOff: zapv2.At[QuasarCertSchema, uint32](40),
|
||||
CoronaLen: zapv2.At[QuasarCertSchema, uint32](44),
|
||||
PulsarOff: zapv2.At[QuasarCertSchema, uint32](48),
|
||||
PulsarLen: zapv2.At[QuasarCertSchema, uint32](52),
|
||||
MagnetarOff: zapv2.At[QuasarCertSchema, uint32](56),
|
||||
MagnetarLen: zapv2.At[QuasarCertSchema, uint32](60),
|
||||
MLDSARollupOff: zapv2.At[QuasarCertSchema, uint32](64),
|
||||
MLDSARollupLen: zapv2.At[QuasarCertSchema, uint32](68),
|
||||
Epoch: zapv1.At[QuasarCertSchema, uint64](8),
|
||||
FinalityUnixNano: zapv1.At[QuasarCertSchema, int64](16),
|
||||
Validators: zapv1.At[QuasarCertSchema, uint32](24),
|
||||
BLSOff: zapv1.At[QuasarCertSchema, uint32](32),
|
||||
BLSLen: zapv1.At[QuasarCertSchema, uint32](36),
|
||||
CoronaOff: zapv1.At[QuasarCertSchema, uint32](40),
|
||||
CoronaLen: zapv1.At[QuasarCertSchema, uint32](44),
|
||||
PulsarOff: zapv1.At[QuasarCertSchema, uint32](48),
|
||||
PulsarLen: zapv1.At[QuasarCertSchema, uint32](52),
|
||||
MagnetarOff: zapv1.At[QuasarCertSchema, uint32](56),
|
||||
MagnetarLen: zapv1.At[QuasarCertSchema, uint32](60),
|
||||
MLDSARollupOff: zapv1.At[QuasarCertSchema, uint32](64),
|
||||
MLDSARollupLen: zapv1.At[QuasarCertSchema, uint32](68),
|
||||
}
|
||||
|
||||
// NewQuasarCert builds a fresh QuasarCert in a ZAP buffer.
|
||||
@@ -104,7 +104,7 @@ var QuasarCertSchemaFields = struct {
|
||||
// [*Builder.StartObject], [*ObjectBuilder.Set*], [*Builder.Finish])
|
||||
// so the entire build expands at the call site. Result: 1 heap
|
||||
// alloc (the buffer), zero overhead vs v1.
|
||||
func NewQuasarCert(epoch uint64, finalityUnixNano int64, validators uint32, bLSOff uint32, bLSLen uint32, coronaOff uint32, coronaLen uint32, pulsarOff uint32, pulsarLen uint32, magnetarOff uint32, magnetarLen uint32, mLDSARollupOff uint32, mLDSARollupLen uint32) (zapv2.View[QuasarCertSchema], []byte) {
|
||||
func NewQuasarCert(epoch uint64, finalityUnixNano int64, validators uint32, bLSOff uint32, bLSLen uint32, coronaOff uint32, coronaLen uint32, pulsarOff uint32, pulsarLen uint32, magnetarOff uint32, magnetarLen uint32, mLDSARollupOff uint32, mLDSARollupLen uint32) (zapv1.View[QuasarCertSchema], []byte) {
|
||||
b := zap.NewBuilder(zap.HeaderSize + SizeQuasarCert)
|
||||
ob := b.StartObject(SizeQuasarCert)
|
||||
ob.SetUint8(0, uint8(KindQuasarCert))
|
||||
@@ -124,26 +124,26 @@ func NewQuasarCert(epoch uint64, finalityUnixNano int64, validators uint32, bLSO
|
||||
rootOff := ob.FinishAsRoot()
|
||||
buf := b.Finish()
|
||||
end := rootOff + SizeQuasarCert
|
||||
return zapv2.AsView[QuasarCertSchema](zapv2.RawFromSlices(buf, rootOff, end)), buf
|
||||
return zapv1.AsView[QuasarCertSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
||||
}
|
||||
|
||||
// WrapQuasarCert parses a ZAP buffer into a typed
|
||||
// [zapv2.View[QuasarCert]]. Validates the wire frame and the kind
|
||||
// discriminator at offset 0; returns [*zapv2.SchemaError] on kind
|
||||
// [zapv1.View[QuasarCert]]. 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 WrapQuasarCert(b []byte) (zapv2.View[QuasarCertSchema], error) {
|
||||
func WrapQuasarCert(b []byte) (zapv1.View[QuasarCertSchema], error) {
|
||||
msg, err := zap.Parse(b)
|
||||
if err != nil {
|
||||
return zapv2.View[QuasarCertSchema]{}, err
|
||||
return zapv1.View[QuasarCertSchema]{}, err
|
||||
}
|
||||
root := msg.Root()
|
||||
if got := root.Uint8(0); got != uint8(KindQuasarCert) {
|
||||
return zapv2.View[QuasarCertSchema]{}, zapv2.NewSchemaError(
|
||||
KindQuasarCert, zapv2.KindByte(got), "QuasarCert")
|
||||
return zapv1.View[QuasarCertSchema]{}, zapv1.NewSchemaError(
|
||||
KindQuasarCert, zapv1.KindByte(got), "QuasarCert")
|
||||
}
|
||||
data := msg.Bytes()
|
||||
rootOff := root.Offset()
|
||||
@@ -151,6 +151,6 @@ func WrapQuasarCert(b []byte) (zapv2.View[QuasarCertSchema], error) {
|
||||
if end > len(data) {
|
||||
end = len(data) // Read returns zero on OOB; v1 graceful degradation
|
||||
}
|
||||
return zapv2.AsView[QuasarCertSchema](zapv2.RawFromSlices(data, rootOff, end)), nil
|
||||
return zapv1.AsView[QuasarCertSchema](zapv1.RawFromSlices(data, rootOff, end)), nil
|
||||
}
|
||||
|
||||
+12
-12
@@ -21,7 +21,7 @@ import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// TestQuasarCert_RoundTrip: build with distinctive values for every
|
||||
@@ -72,25 +72,25 @@ func TestQuasarCert_RoundTrip(t *testing.T) {
|
||||
t.Fatalf("WrapQuasarCert: %v", err)
|
||||
}
|
||||
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.Epoch); got != want.Epoch {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.Epoch); got != want.Epoch {
|
||||
t.Errorf("Epoch = %#x; want %#x", got, want.Epoch)
|
||||
}
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.FinalityUnixNano); got != want.FinalityUnixNano {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.FinalityUnixNano); got != want.FinalityUnixNano {
|
||||
t.Errorf("FinalityUnixNano = %d; want %d", got, want.FinalityUnixNano)
|
||||
}
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.Validators); got != want.Validators {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.Validators); got != want.Validators {
|
||||
t.Errorf("Validators = %d; want %d", got, want.Validators)
|
||||
}
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.BLSOff); got != want.BLSOff {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.BLSOff); got != want.BLSOff {
|
||||
t.Errorf("BLSOff = %#x; want %#x", got, want.BLSOff)
|
||||
}
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.BLSLen); got != want.BLSLen {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.BLSLen); got != want.BLSLen {
|
||||
t.Errorf("BLSLen = %d; want %d", got, want.BLSLen)
|
||||
}
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.PulsarLen); got != want.PulsarLen {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.PulsarLen); got != want.PulsarLen {
|
||||
t.Errorf("PulsarLen = %d; want %d", got, want.PulsarLen)
|
||||
}
|
||||
if got := zapv2.Read(view2, QuasarCertSchemaFields.MLDSARollupOff); got != want.MLDSARollupOff {
|
||||
if got := zapv1.Read(view2, QuasarCertSchemaFields.MLDSARollupOff); got != want.MLDSARollupOff {
|
||||
t.Errorf("MLDSARollupOff = %#x; want %#x", got, want.MLDSARollupOff)
|
||||
}
|
||||
}
|
||||
@@ -114,8 +114,8 @@ func TestQuasarCert_KindMismatch(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("expected SchemaError on kind mismatch")
|
||||
}
|
||||
if _, ok := err.(*zapv2.SchemaError); !ok {
|
||||
t.Errorf("expected *zapv2.SchemaError, got %T: %v", err, err)
|
||||
if _, ok := err.(*zapv1.SchemaError); !ok {
|
||||
t.Errorf("expected *zapv1.SchemaError, got %T: %v", err, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,11 +141,11 @@ func TestQuasarCert_Metadata(t *testing.T) {
|
||||
// TestQuasarCert_NotRegistered: the LP-182 consensus-wire schemas
|
||||
// explicitly skip global registration because their 0x01..0x0D kind
|
||||
// bytes are LOCAL to the consensus wire registry, not the global
|
||||
// zapv2.DefaultRegistry that hosts LP-201 (0xD0+) and LP-214 (0xF0+).
|
||||
// zapv1.DefaultRegistry that hosts LP-201 (0xD0+) and LP-214 (0xF0+).
|
||||
// Verify init() did NOT register QuasarCert globally.
|
||||
func TestQuasarCert_NotRegistered(t *testing.T) {
|
||||
t.Parallel()
|
||||
if entry, ok := zapv2.DefaultRegistry.Lookup(KindQuasarCert); ok {
|
||||
if entry, ok := zapv1.DefaultRegistry.Lookup(KindQuasarCert); ok {
|
||||
// 0x01 might be claimed by some unrelated schema in the same test
|
||||
// binary. Only fail if the entry's name is ours — that would mean
|
||||
// the codegen ignored skip_registry.
|
||||
+3
-3
@@ -6,7 +6,7 @@ package zkvmwire
|
||||
import (
|
||||
"testing"
|
||||
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
var benchTxID = [32]byte{
|
||||
@@ -66,7 +66,7 @@ func BenchmarkZKVMUTXO_RoundTrip(b *testing.B) {
|
||||
if err != nil {
|
||||
b.Fatalf("Wrap: %v", err)
|
||||
}
|
||||
_ = zapv2.Read(view, ZKVMUTXOSchemaFields.Height)
|
||||
_ = zapv1.Read(view, ZKVMUTXOSchemaFields.Height)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ func BenchmarkZKVMUTXO_Read(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = zapv2.Read(view, ZKVMUTXOSchemaFields.Height)
|
||||
_ = zapv1.Read(view, ZKVMUTXOSchemaFields.Height)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -21,7 +21,7 @@ import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// TestZKVMUTXO_RoundTrip: build with distinctive values for every
|
||||
@@ -71,22 +71,22 @@ func TestZKVMUTXO_RoundTrip(t *testing.T) {
|
||||
t.Fatalf("WrapZKVMUTXO: %v", err)
|
||||
}
|
||||
|
||||
if got := zapv2.Read(view2, ZKVMUTXOSchemaFields.OutputIndex); got != want.OutputIndex {
|
||||
if got := zapv1.Read(view2, ZKVMUTXOSchemaFields.OutputIndex); got != want.OutputIndex {
|
||||
t.Errorf("OutputIndex = %#x; want %#x", got, want.OutputIndex)
|
||||
}
|
||||
if got := zapv2.Read(view2, ZKVMUTXOSchemaFields.Height); got != want.Height {
|
||||
if got := zapv1.Read(view2, ZKVMUTXOSchemaFields.Height); got != want.Height {
|
||||
t.Errorf("Height = %#x; want %#x", got, want.Height)
|
||||
}
|
||||
if got := zapv2.Read(view2, ZKVMUTXOSchemaFields.CommitmentOff); got != want.CommitmentOff {
|
||||
if got := zapv1.Read(view2, ZKVMUTXOSchemaFields.CommitmentOff); got != want.CommitmentOff {
|
||||
t.Errorf("CommitmentOff = %#x; want %#x", got, want.CommitmentOff)
|
||||
}
|
||||
if got := zapv2.Read(view2, ZKVMUTXOSchemaFields.CommitmentLen); got != want.CommitmentLen {
|
||||
if got := zapv1.Read(view2, ZKVMUTXOSchemaFields.CommitmentLen); got != want.CommitmentLen {
|
||||
t.Errorf("CommitmentLen = %d; want %d", got, want.CommitmentLen)
|
||||
}
|
||||
if got := zapv2.Read(view2, ZKVMUTXOSchemaFields.CiphertextLen); got != want.CiphertextLen {
|
||||
if got := zapv1.Read(view2, ZKVMUTXOSchemaFields.CiphertextLen); got != want.CiphertextLen {
|
||||
t.Errorf("CiphertextLen = %d; want %d", got, want.CiphertextLen)
|
||||
}
|
||||
if got := zapv2.Read(view2, ZKVMUTXOSchemaFields.EphemeralPKOff); got != want.EphemeralPKOff {
|
||||
if got := zapv1.Read(view2, ZKVMUTXOSchemaFields.EphemeralPKOff); got != want.EphemeralPKOff {
|
||||
t.Errorf("EphemeralPKOff = %#x; want %#x", got, want.EphemeralPKOff)
|
||||
}
|
||||
|
||||
@@ -116,8 +116,8 @@ func TestZKVMUTXO_KindMismatch(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("expected SchemaError on kind mismatch")
|
||||
}
|
||||
if _, ok := err.(*zapv2.SchemaError); !ok {
|
||||
t.Errorf("expected *zapv2.SchemaError, got %T: %v", err, err)
|
||||
if _, ok := err.(*zapv1.SchemaError); !ok {
|
||||
t.Errorf("expected *zapv1.SchemaError, got %T: %v", err, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ func TestZKVMUTXO_Metadata(t *testing.T) {
|
||||
// NOT register ZKVMUTXO globally.
|
||||
func TestZKVMUTXO_NotRegistered(t *testing.T) {
|
||||
t.Parallel()
|
||||
if entry, ok := zapv2.DefaultRegistry.Lookup(KindZKVMUTXO); ok {
|
||||
if entry, ok := zapv1.DefaultRegistry.Lookup(KindZKVMUTXO); ok {
|
||||
if entry.Name == "ZKVMUTXO" {
|
||||
t.Fatalf("ZKVMUTXOSchema was registered in DefaultRegistry "+
|
||||
"despite skip_registry=true; entry=%+v", entry)
|
||||
+33
-33
@@ -1,28 +1,28 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
//
|
||||
// Code generated by github.com/luxfi/zap/v2/codegen — DO NOT EDIT.
|
||||
// Code generated by github.com/luxfi/zap/v1/codegen — DO NOT EDIT.
|
||||
// Source schema: ZKVMUTXO (kind=0x03, size=72).
|
||||
|
||||
package zkvmwire
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap"
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// KindZKVMUTXO is the wire discriminator for ZKVMUTXO.
|
||||
const KindZKVMUTXO zapv2.KindByte = 0x03
|
||||
const KindZKVMUTXO zapv1.KindByte = 0x03
|
||||
|
||||
// SizeZKVMUTXO is the fixed object payload size in bytes.
|
||||
const SizeZKVMUTXO = 72
|
||||
|
||||
// ZKVMUTXOSchema is the v2 schema marker for ZKVMUTXO. Methods are constant-
|
||||
// returning so concrete-typed [zapv2.Wrap[ZKVMUTXOSchema]] calls fold to
|
||||
// returning so concrete-typed [zapv1.Wrap[ZKVMUTXOSchema]] calls fold to
|
||||
// literals at the call site.
|
||||
type ZKVMUTXOSchema struct{}
|
||||
|
||||
func (ZKVMUTXOSchema) Kind() zapv2.KindByte { return KindZKVMUTXO }
|
||||
func (ZKVMUTXOSchema) Kind() zapv1.KindByte { return KindZKVMUTXO }
|
||||
func (ZKVMUTXOSchema) Size() int { return SizeZKVMUTXO }
|
||||
func (ZKVMUTXOSchema) Name() string { return "ZKVMUTXO" }
|
||||
|
||||
@@ -54,26 +54,26 @@ const OffsetZKVMUTXO_EphemeralPKOff = 64
|
||||
const OffsetZKVMUTXO_EphemeralPKLen = 68
|
||||
|
||||
// ZKVMUTXOSchemaFields is the namespace of every scalar field accessor for ZKVMUTXO.
|
||||
// Use with [zapv2.Read] / [zapv2.Write] for type-safe access.
|
||||
// Use with [zapv1.Read] / [zapv1.Write] for type-safe access.
|
||||
// Byte-array fields are emitted as standalone functions, see below.
|
||||
var ZKVMUTXOSchemaFields = struct {
|
||||
OutputIndex zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
Height zapv2.Field[ZKVMUTXOSchema, uint64]
|
||||
CommitmentOff zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
CommitmentLen zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
CiphertextOff zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
CiphertextLen zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
EphemeralPKOff zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
EphemeralPKLen zapv2.Field[ZKVMUTXOSchema, uint32]
|
||||
OutputIndex zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
Height zapv1.Field[ZKVMUTXOSchema, uint64]
|
||||
CommitmentOff zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
CommitmentLen zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
CiphertextOff zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
CiphertextLen zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
EphemeralPKOff zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
EphemeralPKLen zapv1.Field[ZKVMUTXOSchema, uint32]
|
||||
}{
|
||||
OutputIndex: zapv2.At[ZKVMUTXOSchema, uint32](4),
|
||||
Height: zapv2.At[ZKVMUTXOSchema, uint64](8),
|
||||
CommitmentOff: zapv2.At[ZKVMUTXOSchema, uint32](48),
|
||||
CommitmentLen: zapv2.At[ZKVMUTXOSchema, uint32](52),
|
||||
CiphertextOff: zapv2.At[ZKVMUTXOSchema, uint32](56),
|
||||
CiphertextLen: zapv2.At[ZKVMUTXOSchema, uint32](60),
|
||||
EphemeralPKOff: zapv2.At[ZKVMUTXOSchema, uint32](64),
|
||||
EphemeralPKLen: zapv2.At[ZKVMUTXOSchema, uint32](68),
|
||||
OutputIndex: zapv1.At[ZKVMUTXOSchema, uint32](4),
|
||||
Height: zapv1.At[ZKVMUTXOSchema, uint64](8),
|
||||
CommitmentOff: zapv1.At[ZKVMUTXOSchema, uint32](48),
|
||||
CommitmentLen: zapv1.At[ZKVMUTXOSchema, uint32](52),
|
||||
CiphertextOff: zapv1.At[ZKVMUTXOSchema, uint32](56),
|
||||
CiphertextLen: zapv1.At[ZKVMUTXOSchema, uint32](60),
|
||||
EphemeralPKOff: zapv1.At[ZKVMUTXOSchema, uint32](64),
|
||||
EphemeralPKLen: zapv1.At[ZKVMUTXOSchema, uint32](68),
|
||||
}
|
||||
|
||||
// NewZKVMUTXO builds a fresh ZKVMUTXO in a ZAP buffer.
|
||||
@@ -82,7 +82,7 @@ var ZKVMUTXOSchemaFields = struct {
|
||||
// [*Builder.StartObject], [*ObjectBuilder.Set*], [*Builder.Finish])
|
||||
// so the entire build expands at the call site. Result: 1 heap
|
||||
// alloc (the buffer), zero overhead vs v1.
|
||||
func NewZKVMUTXO(outputIndex uint32, height uint64, commitmentOff uint32, commitmentLen uint32, ciphertextOff uint32, ciphertextLen uint32, ephemeralPKOff uint32, ephemeralPKLen uint32, txID [32]byte) (zapv2.View[ZKVMUTXOSchema], []byte) {
|
||||
func NewZKVMUTXO(outputIndex uint32, height uint64, commitmentOff uint32, commitmentLen uint32, ciphertextOff uint32, ciphertextLen uint32, ephemeralPKOff uint32, ephemeralPKLen uint32, txID [32]byte) (zapv1.View[ZKVMUTXOSchema], []byte) {
|
||||
b := zap.NewBuilder(zap.HeaderSize + SizeZKVMUTXO)
|
||||
ob := b.StartObject(SizeZKVMUTXO)
|
||||
ob.SetUint8(0, uint8(KindZKVMUTXO))
|
||||
@@ -98,26 +98,26 @@ func NewZKVMUTXO(outputIndex uint32, height uint64, commitmentOff uint32, commit
|
||||
rootOff := ob.FinishAsRoot()
|
||||
buf := b.Finish()
|
||||
end := rootOff + SizeZKVMUTXO
|
||||
return zapv2.AsView[ZKVMUTXOSchema](zapv2.RawFromSlices(buf, rootOff, end)), buf
|
||||
return zapv1.AsView[ZKVMUTXOSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
||||
}
|
||||
|
||||
// WrapZKVMUTXO parses a ZAP buffer into a typed
|
||||
// [zapv2.View[ZKVMUTXO]]. Validates the wire frame and the kind
|
||||
// discriminator at offset 0; returns [*zapv2.SchemaError] on kind
|
||||
// [zapv1.View[ZKVMUTXO]]. 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 WrapZKVMUTXO(b []byte) (zapv2.View[ZKVMUTXOSchema], error) {
|
||||
func WrapZKVMUTXO(b []byte) (zapv1.View[ZKVMUTXOSchema], error) {
|
||||
msg, err := zap.Parse(b)
|
||||
if err != nil {
|
||||
return zapv2.View[ZKVMUTXOSchema]{}, err
|
||||
return zapv1.View[ZKVMUTXOSchema]{}, err
|
||||
}
|
||||
root := msg.Root()
|
||||
if got := root.Uint8(0); got != uint8(KindZKVMUTXO) {
|
||||
return zapv2.View[ZKVMUTXOSchema]{}, zapv2.NewSchemaError(
|
||||
KindZKVMUTXO, zapv2.KindByte(got), "ZKVMUTXO")
|
||||
return zapv1.View[ZKVMUTXOSchema]{}, zapv1.NewSchemaError(
|
||||
KindZKVMUTXO, zapv1.KindByte(got), "ZKVMUTXO")
|
||||
}
|
||||
data := msg.Bytes()
|
||||
rootOff := root.Offset()
|
||||
@@ -125,7 +125,7 @@ func WrapZKVMUTXO(b []byte) (zapv2.View[ZKVMUTXOSchema], error) {
|
||||
if end > len(data) {
|
||||
end = len(data) // Read returns zero on OOB; v1 graceful degradation
|
||||
}
|
||||
return zapv2.AsView[ZKVMUTXOSchema](zapv2.RawFromSlices(data, rootOff, end)), nil
|
||||
return zapv1.AsView[ZKVMUTXOSchema](zapv1.RawFromSlices(data, rootOff, end)), nil
|
||||
}
|
||||
|
||||
// ZKVMUTXOTxID reads the 32-byte inline TxID field of ZKVMUTXO.
|
||||
@@ -134,9 +134,9 @@ func WrapZKVMUTXO(b []byte) (zapv2.View[ZKVMUTXOSchema], error) {
|
||||
// a sub-slice of the underlying buffer); the returned [32]byte is a
|
||||
// value copy so the caller's slot owns the bytes after the View's
|
||||
// buffer is freed.
|
||||
func ZKVMUTXOTxID(v zapv2.View[ZKVMUTXOSchema]) [32]byte {
|
||||
func ZKVMUTXOTxID(v zapv1.View[ZKVMUTXOSchema]) [32]byte {
|
||||
msg := zap.WrapBuffer(v.Bytes())
|
||||
obj := msg.RootObjectAt(int(zapv2.RootOff(v)))
|
||||
obj := msg.RootObjectAt(int(zapv1.RootOff(v)))
|
||||
slice := obj.BytesFixedSlice(OffsetZKVMUTXO_TxID, 32)
|
||||
var out [32]byte
|
||||
if len(slice) == 32 {
|
||||
@@ -13,7 +13,7 @@
|
||||
// equality with what was set. This catches regressions in:
|
||||
// - Constructor field-write order vs offsets
|
||||
// - Wrap kind-discriminator check
|
||||
// - Scalar field accessors via zapv2.Read
|
||||
// - Scalar field accessors via zapv1.Read
|
||||
// - Byte-array field accessor (zero-copy slice + value-copy)
|
||||
//
|
||||
// If this test passes, the codegen's emitted files are functionally
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
zapv2 "github.com/luxfi/zap/v2"
|
||||
zapv1 "github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// TestRoundTrip_ScalarsAndBytes: build with a set of distinctive
|
||||
@@ -121,8 +121,8 @@ func TestWrap_KindMismatch(t *testing.T) {
|
||||
t.Fatal("expected SchemaError on kind mismatch")
|
||||
}
|
||||
// Verify it's the typed error, not just any error.
|
||||
if _, ok := err.(*zapv2.SchemaError); !ok {
|
||||
t.Errorf("expected *zapv2.SchemaError, got %T: %v", err, err)
|
||||
if _, ok := err.(*zapv1.SchemaError); !ok {
|
||||
t.Errorf("expected *zapv1.SchemaError, got %T: %v", err, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ func TestSchemaMetadata(t *testing.T) {
|
||||
// registered the schema with the package-level Registry.
|
||||
func TestSchemaRegistered(t *testing.T) {
|
||||
t.Parallel()
|
||||
entry, ok := zapv2.DefaultRegistry.Lookup(KindLightClientBlockHeaderRequest)
|
||||
entry, ok := zapv1.DefaultRegistry.Lookup(KindLightClientBlockHeaderRequest)
|
||||
if !ok {
|
||||
t.Fatal("LCBlockHeaderReqSchema not registered in DefaultRegistry")
|
||||
}
|
||||
@@ -157,23 +157,23 @@ func TestSchemaRegistered(t *testing.T) {
|
||||
}
|
||||
|
||||
// checkScalarFields is the shared assertion helper for TestRoundTrip_*.
|
||||
func checkScalarFields(t *testing.T, v zapv2.View[LCBlockHeaderReqSchema],
|
||||
func checkScalarFields(t *testing.T, v zapv1.View[LCBlockHeaderReqSchema],
|
||||
wantVersion uint8, wantChainID uint32, wantBlockHeight uint64,
|
||||
wantCertMinTier uint8, wantRequestID uint32) {
|
||||
t.Helper()
|
||||
if got := zapv2.Read(v, LCBlockHeaderReqSchemaFields.Version); got != wantVersion {
|
||||
if got := zapv1.Read(v, LCBlockHeaderReqSchemaFields.Version); got != wantVersion {
|
||||
t.Errorf("Version = %d; want %d", got, wantVersion)
|
||||
}
|
||||
if got := zapv2.Read(v, LCBlockHeaderReqSchemaFields.ChainID); got != wantChainID {
|
||||
if got := zapv1.Read(v, LCBlockHeaderReqSchemaFields.ChainID); got != wantChainID {
|
||||
t.Errorf("ChainID = %d; want %d", got, wantChainID)
|
||||
}
|
||||
if got := zapv2.Read(v, LCBlockHeaderReqSchemaFields.BlockHeight); got != wantBlockHeight {
|
||||
if got := zapv1.Read(v, LCBlockHeaderReqSchemaFields.BlockHeight); got != wantBlockHeight {
|
||||
t.Errorf("BlockHeight = 0x%x; want 0x%x", got, wantBlockHeight)
|
||||
}
|
||||
if got := zapv2.Read(v, LCBlockHeaderReqSchemaFields.CertMinTier); got != wantCertMinTier {
|
||||
if got := zapv1.Read(v, LCBlockHeaderReqSchemaFields.CertMinTier); got != wantCertMinTier {
|
||||
t.Errorf("CertMinTier = %d; want %d", got, wantCertMinTier)
|
||||
}
|
||||
if got := zapv2.Read(v, LCBlockHeaderReqSchemaFields.RequestID); got != wantRequestID {
|
||||
if got := zapv1.Read(v, LCBlockHeaderReqSchemaFields.RequestID); got != wantRequestID {
|
||||
t.Errorf("RequestID = %d; want %d", got, wantRequestID)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2_test
|
||||
package zapv1_test
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
// Package zapv2 is the elegant, generic, idiomatic Go reference
|
||||
// Package zapv1 is the elegant, generic, idiomatic Go reference
|
||||
// implementation of the ZAP wire format.
|
||||
//
|
||||
// Where the v1 [github.com/luxfi/zap] package exposes a C-shaped API
|
||||
@@ -46,4 +46,4 @@
|
||||
//
|
||||
// One and only one way to express any of these. No braiding of policy
|
||||
// with primitive, no inheritance, no duplication.
|
||||
package zapv2
|
||||
package zapv1
|
||||
@@ -20,14 +20,14 @@
|
||||
// v2 shape (declarations only; the generic API does the rest):
|
||||
//
|
||||
// type AdvanceTimeSchema struct{}
|
||||
// func (AdvanceTimeSchema) Kind() zapv2.KindByte { return 0x14 }
|
||||
// func (AdvanceTimeSchema) Kind() zapv1.KindByte { return 0x14 }
|
||||
// func (AdvanceTimeSchema) Size() int { return 9 }
|
||||
// func (AdvanceTimeSchema) Name() string { return "AdvanceTimeTx" }
|
||||
//
|
||||
// var AdvanceTimeFields = struct {
|
||||
// Time zapv2.Field[AdvanceTimeSchema, uint64]
|
||||
// Time zapv1.Field[AdvanceTimeSchema, uint64]
|
||||
// }{
|
||||
// Time: zapv2.At[AdvanceTimeSchema, uint64](1),
|
||||
// Time: zapv1.At[AdvanceTimeSchema, uint64](1),
|
||||
// }
|
||||
//
|
||||
// That's it. Wrap, Build, Read, Write are all expressed through the
|
||||
@@ -36,7 +36,7 @@ package examples
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap"
|
||||
"github.com/luxfi/zap/v2"
|
||||
"github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// KindAdvanceTime is the wire discriminator for AdvanceTimeTx. It
|
||||
@@ -45,14 +45,14 @@ import (
|
||||
// advance_time_tx_test.go pins this so the v2 generic builder
|
||||
// produces the exact same bytes as the v1 hand-rolled
|
||||
// NewAdvanceTimeTx.
|
||||
const KindAdvanceTime zapv2.KindByte = 1
|
||||
const KindAdvanceTime zapv1.KindByte = 1
|
||||
|
||||
// AdvanceTimeSchema is the v2 schema marker for AdvanceTimeTx. The
|
||||
// type is the schema's identity; the methods describe its wire shape.
|
||||
type AdvanceTimeSchema struct{}
|
||||
|
||||
// Kind returns the discriminator byte at object offset 0.
|
||||
func (AdvanceTimeSchema) Kind() zapv2.KindByte { return KindAdvanceTime }
|
||||
func (AdvanceTimeSchema) Kind() zapv1.KindByte { return KindAdvanceTime }
|
||||
|
||||
// Size returns the fixed object payload (1 byte kind + 8 byte time).
|
||||
func (AdvanceTimeSchema) Size() int { return 9 }
|
||||
@@ -64,16 +64,16 @@ func (AdvanceTimeSchema) Name() string { return "AdvanceTimeTx" }
|
||||
// AdvanceTimeSchema. There is exactly ONE place where offsets are
|
||||
// declared; everywhere else uses these typed handles.
|
||||
//
|
||||
// Reading: zapv2.Read(view, AdvanceTimeFields.Time) → uint64
|
||||
// Writing: zapv2.Write(setter, AdvanceTimeFields.Time, ts)
|
||||
// Reading: zapv1.Read(view, AdvanceTimeFields.Time) → uint64
|
||||
// Writing: zapv1.Write(setter, AdvanceTimeFields.Time, ts)
|
||||
//
|
||||
// A compile error guards against using these handles with any view
|
||||
// other than View[AdvanceTimeSchema] — see
|
||||
// _compile_fail_test/cross_schema_field.go for the demonstration.
|
||||
var AdvanceTimeFields = struct {
|
||||
Time zapv2.Field[AdvanceTimeSchema, uint64]
|
||||
Time zapv1.Field[AdvanceTimeSchema, uint64]
|
||||
}{
|
||||
Time: zapv2.At[AdvanceTimeSchema, uint64](1),
|
||||
Time: zapv1.At[AdvanceTimeSchema, uint64](1),
|
||||
}
|
||||
|
||||
// NewAdvanceTime builds a fresh AdvanceTimeTx with the given
|
||||
@@ -87,12 +87,12 @@ var AdvanceTimeFields = struct {
|
||||
// itself). Result: matches v1's hand-rolled 1-alloc / 48-B profile.
|
||||
//
|
||||
// This pattern is what a codegen tool would emit per schema. The
|
||||
// generic [zapv2.NewBuilderFor] / [zapv2.Build] paths are equivalent
|
||||
// generic [zapv1.NewBuilderFor] / [zapv1.Build] paths are equivalent
|
||||
// in wire semantics but incur extra allocations because Go generics
|
||||
// hide the inlineable v1 primitives behind a non-inlineable shape
|
||||
// function — see the BENCH_RESULTS table for the measured cost
|
||||
// breakdown.
|
||||
func NewAdvanceTime(ts uint64) (zapv2.View[AdvanceTimeSchema], []byte) {
|
||||
func NewAdvanceTime(ts uint64) (zapv1.View[AdvanceTimeSchema], []byte) {
|
||||
const size = 9 // AdvanceTimeSchema{}.Size()
|
||||
b := zap.NewBuilder(zap.HeaderSize + size)
|
||||
ob := b.StartObject(size)
|
||||
@@ -101,7 +101,7 @@ func NewAdvanceTime(ts uint64) (zapv2.View[AdvanceTimeSchema], []byte) {
|
||||
rootOff := ob.FinishAsRoot()
|
||||
buf := b.Finish()
|
||||
end := rootOff + size
|
||||
return zapv2.AsView[AdvanceTimeSchema](zapv2.RawFromSlices(buf, rootOff, end)), buf
|
||||
return zapv1.AsView[AdvanceTimeSchema](zapv1.RawFromSlices(buf, rootOff, end)), buf
|
||||
}
|
||||
|
||||
// NewAdvanceTimeClosure is the closure-style equivalent of
|
||||
@@ -109,9 +109,9 @@ func NewAdvanceTime(ts uint64) (zapv2.View[AdvanceTimeSchema], []byte) {
|
||||
// like English at the call site, at the cost of ~3 extra allocations
|
||||
// per Build. Use it for cold paths (CLI tools, test fixtures) and
|
||||
// reach for the imperative form on hot paths (per-block tx assembly).
|
||||
func NewAdvanceTimeClosure(ts uint64) (zapv2.View[AdvanceTimeSchema], []byte) {
|
||||
return zapv2.Build[AdvanceTimeSchema](func(s zapv2.Setter[AdvanceTimeSchema]) {
|
||||
zapv2.Write(s, AdvanceTimeFields.Time, ts)
|
||||
func NewAdvanceTimeClosure(ts uint64) (zapv1.View[AdvanceTimeSchema], []byte) {
|
||||
return zapv1.Build[AdvanceTimeSchema](func(s zapv1.Setter[AdvanceTimeSchema]) {
|
||||
zapv1.Write(s, AdvanceTimeFields.Time, ts)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -119,28 +119,28 @@ func NewAdvanceTimeClosure(ts uint64) (zapv2.View[AdvanceTimeSchema], []byte) {
|
||||
//
|
||||
// Per-schema hand-rolled fast path: parses the wire frame inline,
|
||||
// validates the kind discriminator, and composes a typed
|
||||
// [zapv2.View[AdvanceTimeSchema]]. Result: matches v1 hand-rolled
|
||||
// [zapv1.View[AdvanceTimeSchema]]. Result: matches v1 hand-rolled
|
||||
// performance to within compiler noise. Zero heap allocs on the
|
||||
// happy path.
|
||||
//
|
||||
// Defense-in-depth: the explicit payload bounds check is folded into
|
||||
// the per-Read bounds check that lives in [zapv2.Read] — wrapping a
|
||||
// the per-Read bounds check that lives in [zapv1.Read] — wrapping a
|
||||
// short buffer succeeds, but any out-of-range Read returns the zero
|
||||
// value (matches v1 graceful-degradation semantics, see
|
||||
// [zap.Object.Uint64]).
|
||||
//
|
||||
// This pattern is what a codegen tool emits per schema. For cold
|
||||
// paths where ergonomics matter more than the last few ns, use the
|
||||
// generic [zapv2.Wrap[AdvanceTimeSchema]] instead.
|
||||
func WrapAdvanceTime(b []byte) (zapv2.View[AdvanceTimeSchema], error) {
|
||||
// generic [zapv1.Wrap[AdvanceTimeSchema]] instead.
|
||||
func WrapAdvanceTime(b []byte) (zapv1.View[AdvanceTimeSchema], error) {
|
||||
const size = 9 // AdvanceTimeSchema{}.Size()
|
||||
msg, err := zap.Parse(b)
|
||||
if err != nil {
|
||||
return zapv2.View[AdvanceTimeSchema]{}, err
|
||||
return zapv1.View[AdvanceTimeSchema]{}, err
|
||||
}
|
||||
root := msg.Root()
|
||||
if got := root.Uint8(0); got != uint8(KindAdvanceTime) {
|
||||
return zapv2.View[AdvanceTimeSchema]{},
|
||||
return zapv1.View[AdvanceTimeSchema]{},
|
||||
advanceTimeKindError(got)
|
||||
}
|
||||
data := msg.Bytes()
|
||||
@@ -149,8 +149,8 @@ func WrapAdvanceTime(b []byte) (zapv2.View[AdvanceTimeSchema], error) {
|
||||
if end > len(data) {
|
||||
end = len(data)
|
||||
}
|
||||
return zapv2.AsView[AdvanceTimeSchema](
|
||||
zapv2.RawFromSlices(data, rootOff, end)), nil
|
||||
return zapv1.AsView[AdvanceTimeSchema](
|
||||
zapv1.RawFromSlices(data, rootOff, end)), nil
|
||||
}
|
||||
|
||||
// advanceTimeKindError builds the kind-mismatch error for
|
||||
@@ -159,9 +159,9 @@ func WrapAdvanceTime(b []byte) (zapv2.View[AdvanceTimeSchema], error) {
|
||||
// possible — when [WrapAdvanceTime] inlines into the caller, the
|
||||
// error path stays an out-of-line tail call.
|
||||
func advanceTimeKindError(got uint8) error {
|
||||
return zapv2.NewSchemaError(
|
||||
zapv2.KindByte(KindAdvanceTime),
|
||||
zapv2.KindByte(got),
|
||||
return zapv1.NewSchemaError(
|
||||
zapv1.KindByte(KindAdvanceTime),
|
||||
zapv1.KindByte(got),
|
||||
"AdvanceTimeTx")
|
||||
}
|
||||
|
||||
@@ -169,15 +169,15 @@ func advanceTimeKindError(got uint8) error {
|
||||
// advance to. Zero copy, zero allocation.
|
||||
//
|
||||
// This is the value-side accessor — a thin one-line wrapper around
|
||||
// zapv2.Read for callers who prefer method syntax. It is NOT what
|
||||
// you'd write in a fresh project; just use zapv2.Read(view, Fields.X)
|
||||
// zapv1.Read for callers who prefer method syntax. It is NOT what
|
||||
// you'd write in a fresh project; just use zapv1.Read(view, Fields.X)
|
||||
// directly. Kept here so the example covers both forms.
|
||||
func Time(v zapv2.View[AdvanceTimeSchema]) uint64 {
|
||||
return zapv2.Read(v, AdvanceTimeFields.Time)
|
||||
func Time(v zapv1.View[AdvanceTimeSchema]) uint64 {
|
||||
return zapv1.Read(v, AdvanceTimeFields.Time)
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Register with the package-level Registry so generic dispatch
|
||||
// (PeekKind → Registry.Lookup → WrapAs) finds this schema.
|
||||
zapv2.Register[AdvanceTimeSchema](zapv2.DefaultRegistry)
|
||||
zapv1.Register[AdvanceTimeSchema](zapv1.DefaultRegistry)
|
||||
}
|
||||
@@ -4,15 +4,15 @@
|
||||
package examples
|
||||
|
||||
import (
|
||||
"github.com/luxfi/zap/v2"
|
||||
"github.com/luxfi/zap/v1"
|
||||
)
|
||||
|
||||
// KindBatch is the wire discriminator for BatchTx. Distinct from
|
||||
// KindAdvanceTime so Registry dispatch can tell them apart.
|
||||
const KindBatch zapv2.KindByte = 0x21
|
||||
const KindBatch zapv1.KindByte = 0x21
|
||||
|
||||
// BatchSchema is a small, multi-element schema used to exercise the
|
||||
// generic [zapv2.List] iter.Seq path in tests. Object layout:
|
||||
// generic [zapv1.List] iter.Seq path in tests. Object layout:
|
||||
//
|
||||
// @0: KindBatch (uint8)
|
||||
// @1: BatchID (uint64)
|
||||
@@ -22,54 +22,54 @@ const KindBatch zapv2.KindByte = 0x21
|
||||
// uint64).
|
||||
type BatchSchema struct{}
|
||||
|
||||
func (BatchSchema) Kind() zapv2.KindByte { return KindBatch }
|
||||
func (BatchSchema) Kind() zapv1.KindByte { return KindBatch }
|
||||
func (BatchSchema) Size() int { return 17 }
|
||||
func (BatchSchema) Name() string { return "BatchTx" }
|
||||
|
||||
// KindItem identifies ItemSchema. Items live inside BatchTx lists; an
|
||||
// Item is never a top-level message, but it has a Kind anyway so the
|
||||
// generic List[Item] code can use the same machinery.
|
||||
const KindItem zapv2.KindByte = 0x22
|
||||
const KindItem zapv1.KindByte = 0x22
|
||||
|
||||
// ItemSchema is the per-element schema for BatchTx.Items.
|
||||
type ItemSchema struct{}
|
||||
|
||||
func (ItemSchema) Kind() zapv2.KindByte { return KindItem }
|
||||
func (ItemSchema) Kind() zapv1.KindByte { return KindItem }
|
||||
func (ItemSchema) Size() int { return 16 } // 8 + 8
|
||||
func (ItemSchema) Name() string { return "BatchItem" }
|
||||
|
||||
// BatchFields declares the offsets for BatchSchema.
|
||||
var BatchFields = struct {
|
||||
ID zapv2.Field[BatchSchema, uint64]
|
||||
ID zapv1.Field[BatchSchema, uint64]
|
||||
}{
|
||||
ID: zapv2.At[BatchSchema, uint64](1),
|
||||
ID: zapv1.At[BatchSchema, uint64](1),
|
||||
}
|
||||
|
||||
// ItemFields declares the offsets for ItemSchema.
|
||||
var ItemFields = struct {
|
||||
ID zapv2.Field[ItemSchema, uint64]
|
||||
Value zapv2.Field[ItemSchema, uint64]
|
||||
ID zapv1.Field[ItemSchema, uint64]
|
||||
Value zapv1.Field[ItemSchema, uint64]
|
||||
}{
|
||||
ID: zapv2.At[ItemSchema, uint64](0),
|
||||
Value: zapv2.At[ItemSchema, uint64](8),
|
||||
ID: zapv1.At[ItemSchema, uint64](0),
|
||||
Value: zapv1.At[ItemSchema, uint64](8),
|
||||
}
|
||||
|
||||
// OffsetBatchItems is the byte offset of the list pointer for Items
|
||||
// within the BatchSchema fixed payload. Items is a variable-length
|
||||
// list, so it lives outside the [zapv2.Field] generic vocabulary; it
|
||||
// is read via [zapv2.ListAt] instead.
|
||||
// list, so it lives outside the [zapv1.Field] generic vocabulary; it
|
||||
// is read via [zapv1.ListAt] instead.
|
||||
const OffsetBatchItems uint32 = 9
|
||||
|
||||
// Items returns the list of items in the batch as an [iter.Seq]-ready
|
||||
// [zapv2.List][ItemSchema]. Range-over-func:
|
||||
// [zapv1.List][ItemSchema]. Range-over-func:
|
||||
//
|
||||
// for item := range examples.Items(batchView).All() {
|
||||
// id := zapv2.Read(item, examples.ItemFields.ID)
|
||||
// value := zapv2.Read(item, examples.ItemFields.Value)
|
||||
// id := zapv1.Read(item, examples.ItemFields.ID)
|
||||
// value := zapv1.Read(item, examples.ItemFields.Value)
|
||||
// // ...
|
||||
// }
|
||||
func Items(v zapv2.View[BatchSchema]) zapv2.List[ItemSchema] {
|
||||
return zapv2.ListAt[BatchSchema, ItemSchema](v, OffsetBatchItems)
|
||||
func Items(v zapv1.View[BatchSchema]) zapv1.List[ItemSchema] {
|
||||
return zapv1.ListAt[BatchSchema, ItemSchema](v, OffsetBatchItems)
|
||||
}
|
||||
|
||||
// Item is a value-shaped helper for batch-construction tests.
|
||||
@@ -79,15 +79,15 @@ type Item struct {
|
||||
}
|
||||
|
||||
// NewBatch builds a BatchTx with the given ID and items.
|
||||
func NewBatch(id uint64, items []Item) (zapv2.View[BatchSchema], []byte) {
|
||||
return zapv2.Build[BatchSchema](func(s zapv2.Setter[BatchSchema]) {
|
||||
zapv2.Write(s, BatchFields.ID, id)
|
||||
zapv2.WriteList[BatchSchema, ItemSchema](s, OffsetBatchItems,
|
||||
func(es *zapv2.ElemSetter[ItemSchema]) {
|
||||
func NewBatch(id uint64, items []Item) (zapv1.View[BatchSchema], []byte) {
|
||||
return zapv1.Build[BatchSchema](func(s zapv1.Setter[BatchSchema]) {
|
||||
zapv1.Write(s, BatchFields.ID, id)
|
||||
zapv1.WriteList[BatchSchema, ItemSchema](s, OffsetBatchItems,
|
||||
func(es *zapv1.ElemSetter[ItemSchema]) {
|
||||
for _, it := range items {
|
||||
es.Append(func(e zapv2.Setter[ItemSchema]) {
|
||||
zapv2.Write(e, ItemFields.ID, it.ID)
|
||||
zapv2.Write(e, ItemFields.Value, it.Value)
|
||||
es.Append(func(e zapv1.Setter[ItemSchema]) {
|
||||
zapv1.Write(e, ItemFields.ID, it.ID)
|
||||
zapv1.Write(e, ItemFields.Value, it.Value)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -95,6 +95,6 @@ func NewBatch(id uint64, items []Item) (zapv2.View[BatchSchema], []byte) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
zapv2.Register[BatchSchema](zapv2.DefaultRegistry)
|
||||
zapv2.Register[ItemSchema](zapv2.DefaultRegistry)
|
||||
zapv1.Register[BatchSchema](zapv1.DefaultRegistry)
|
||||
zapv1.Register[ItemSchema](zapv1.DefaultRegistry)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
// methods of generic types ([View[S].Read[T] would be illegal]). v2
|
||||
// therefore exposes Read and Write as top-level generic functions
|
||||
// rather than methods on [View] / [Setter]. The call site is at least
|
||||
// as terse as a method call: `zapv2.Read(view, F.Time)`.
|
||||
// as terse as a method call: `zapv1.Read(view, F.Time)`.
|
||||
type Field[S Schema, T FieldKind] struct {
|
||||
Offset uint32
|
||||
// _phantom keeps the nominal type identity tight: without it the
|
||||
@@ -57,9 +57,9 @@ type phantomCarrier[S Schema, T FieldKind] struct {
|
||||
// fixed-size payload. Construct fields once per schema:
|
||||
//
|
||||
// var AdvanceTimeFields = struct {
|
||||
// Time zapv2.Field[AdvanceTimeSchema, uint64]
|
||||
// Time zapv1.Field[AdvanceTimeSchema, uint64]
|
||||
// }{
|
||||
// Time: zapv2.At[AdvanceTimeSchema, uint64](1),
|
||||
// Time: zapv1.At[AdvanceTimeSchema, uint64](1),
|
||||
// }
|
||||
//
|
||||
// The offset is in bytes. The caller is responsible for keeping
|
||||
@@ -148,7 +148,7 @@ func init() {
|
||||
if *(*[2]byte)(unsafe.Pointer(&u)) != [2]byte{1, 0} {
|
||||
// readBE path would need to be wired here. The package
|
||||
// currently only targets little-endian platforms.
|
||||
panic("zapv2: big-endian host detected; direct-load Read path " +
|
||||
panic("zapv1: big-endian host detected; direct-load Read path " +
|
||||
"requires per-T byteswap (see field.go).")
|
||||
}
|
||||
}
|
||||
@@ -178,8 +178,8 @@ func Write[S Schema, T FieldKind](s Setter[S], f Field[S, T], val T) {
|
||||
// WriteB is the [Builder]-receiver counterpart to [Write]. Used in
|
||||
// the imperative-style build path:
|
||||
//
|
||||
// bb := zapv2.NewBuilderFor[Schema]()
|
||||
// zapv2.WriteB(bb, Fields.Time, ts)
|
||||
// bb := zapv1.NewBuilderFor[Schema]()
|
||||
// zapv1.WriteB(bb, Fields.Time, ts)
|
||||
// view, buf := bb.Finish()
|
||||
//
|
||||
// Identical wire semantics to Write — the difference is only that
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import "iter"
|
||||
|
||||
+10
-10
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import (
|
||||
"iter"
|
||||
@@ -62,7 +62,7 @@ func (l List[E]) At(i int) View[E] {
|
||||
// range-over-func form:
|
||||
//
|
||||
// for view := range list.All() {
|
||||
// t := zapv2.Read(view, EFields.Time)
|
||||
// t := zapv1.Read(view, EFields.Time)
|
||||
// // ...
|
||||
// }
|
||||
//
|
||||
@@ -122,7 +122,7 @@ func (l List[E]) All() iter.Seq[View[E]] {
|
||||
// Usage:
|
||||
//
|
||||
// for payload := range list.Payloads() {
|
||||
// v := zapv2.ReadPayload[ItemSchema, uint64](payload, ItemFields.Value)
|
||||
// v := zapv1.ReadPayload[ItemSchema, uint64](payload, ItemFields.Value)
|
||||
// // ...
|
||||
// }
|
||||
func (l List[E]) Payloads() iter.Seq[[]byte] {
|
||||
@@ -241,14 +241,14 @@ func rawListOffset(l zap.List) int {
|
||||
//
|
||||
// Example (BatchTx.Items, see examples/batch_tx.go):
|
||||
//
|
||||
// zapv2.Build[BatchSchema](func(s zapv2.Setter[BatchSchema]) {
|
||||
// zapv2.Write(s, BatchFields.ID, batchID)
|
||||
// zapv2.WriteList[BatchSchema, ItemSchema](s, OffsetBatchItems,
|
||||
// func(items *zapv2.ElemSetter[ItemSchema]) {
|
||||
// zapv1.Build[BatchSchema](func(s zapv1.Setter[BatchSchema]) {
|
||||
// zapv1.Write(s, BatchFields.ID, batchID)
|
||||
// zapv1.WriteList[BatchSchema, ItemSchema](s, OffsetBatchItems,
|
||||
// func(items *zapv1.ElemSetter[ItemSchema]) {
|
||||
// for _, it := range source {
|
||||
// items.Append(func(e zapv2.Setter[ItemSchema]) {
|
||||
// zapv2.Write(e, ItemFields.ID, it.id)
|
||||
// zapv2.Write(e, ItemFields.Value, it.val)
|
||||
// items.Append(func(e zapv1.Setter[ItemSchema]) {
|
||||
// zapv1.Write(e, ItemFields.ID, it.id)
|
||||
// zapv1.Write(e, ItemFields.Value, it.val)
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import "sync"
|
||||
|
||||
@@ -9,7 +9,7 @@ import "sync"
|
||||
// dedicated sync.Pool + Get + Put per type as v1 did, register a
|
||||
// constructor once:
|
||||
//
|
||||
// var ViewPool = zapv2.NewPool(func() *View[AdvanceTimeSchema] {
|
||||
// var ViewPool = zapv1.NewPool(func() *View[AdvanceTimeSchema] {
|
||||
// return &View[AdvanceTimeSchema]{}
|
||||
// })
|
||||
//
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -58,7 +58,7 @@ type Entry struct {
|
||||
// goroutines, but the typical pattern is init():
|
||||
//
|
||||
// func init() {
|
||||
// zapv2.Register[AdvanceTimeSchema](DefaultRegistry)
|
||||
// zapv1.Register[AdvanceTimeSchema](DefaultRegistry)
|
||||
// }
|
||||
//
|
||||
// Register panics if two schemas declare the same kind byte — that
|
||||
@@ -72,7 +72,7 @@ func Register[S Schema](r *Registry) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if existing, ok := r.entries[kind]; ok && existing.Name != name {
|
||||
panic("zapv2: duplicate kind byte " + hexByte(byte(kind)) +
|
||||
panic("zapv1: duplicate kind byte " + hexByte(byte(kind)) +
|
||||
" for schemas " + existing.Name + " and " + name)
|
||||
}
|
||||
r.entries[kind] = Entry{
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
// KindByte is the one-byte discriminator at offset 0 of every v2
|
||||
// object payload. It identifies the schema concretely.
|
||||
@@ -70,7 +70,7 @@ type SchemaError struct {
|
||||
func (e *SchemaError) Error() string {
|
||||
// Keep the message terse and machine-grep-friendly: the kind bytes
|
||||
// are the load-bearing identity, the name is human help.
|
||||
return "zapv2: schema mismatch: want " + e.Name +
|
||||
return "zapv1: schema mismatch: want " + e.Name +
|
||||
" (kind=" + hexByte(byte(e.Want)) +
|
||||
"), got kind=" + hexByte(byte(e.Got))
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2_test
|
||||
package zapv1_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/zap"
|
||||
"github.com/luxfi/zap/v2"
|
||||
"github.com/luxfi/zap/v2/examples"
|
||||
"github.com/luxfi/zap/v1"
|
||||
"github.com/luxfi/zap/v1/examples"
|
||||
)
|
||||
|
||||
// TestRoundTrip_AdvanceTime: Build → Wrap → Read returns the original
|
||||
@@ -20,14 +20,14 @@ func TestRoundTrip_AdvanceTime(t *testing.T) {
|
||||
cases := []uint64{0, 1, 0xdeadbeef, 1<<63 - 1, 1<<64 - 1}
|
||||
for _, want := range cases {
|
||||
view, buf := examples.NewAdvanceTime(want)
|
||||
if got := zapv2.Read(view, examples.AdvanceTimeFields.Time); got != want {
|
||||
if got := zapv1.Read(view, examples.AdvanceTimeFields.Time); got != want {
|
||||
t.Fatalf("Build→Read: got %d, want %d", got, want)
|
||||
}
|
||||
view2, err := examples.WrapAdvanceTime(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Wrap: %v", err)
|
||||
}
|
||||
if got := zapv2.Read(view2, examples.AdvanceTimeFields.Time); got != want {
|
||||
if got := zapv1.Read(view2, examples.AdvanceTimeFields.Time); got != want {
|
||||
t.Fatalf("Build→Wrap→Read: got %d, want %d", got, want)
|
||||
}
|
||||
// Also exercise the method-style accessor.
|
||||
@@ -45,74 +45,74 @@ func TestRoundTrip_8Shapes(t *testing.T) {
|
||||
type s1 struct{}
|
||||
// Shape 1: bool field
|
||||
t.Run("Bool", func(t *testing.T) {
|
||||
view, _ := zapv2.Build[boolSchema](func(set zapv2.Setter[boolSchema]) {
|
||||
zapv2.Write(set, boolFields.Flag, true)
|
||||
view, _ := zapv1.Build[boolSchema](func(set zapv1.Setter[boolSchema]) {
|
||||
zapv1.Write(set, boolFields.Flag, true)
|
||||
})
|
||||
if !zapv2.Read(view, boolFields.Flag) {
|
||||
if !zapv1.Read(view, boolFields.Flag) {
|
||||
t.Fatal("bool round-trip lost the value")
|
||||
}
|
||||
})
|
||||
// Shape 2..N: integer widths.
|
||||
t.Run("Int8", func(t *testing.T) {
|
||||
const want int8 = -42
|
||||
view, _ := zapv2.Build[i8Schema](func(s zapv2.Setter[i8Schema]) {
|
||||
zapv2.Write(s, i8Fields.V, want)
|
||||
view, _ := zapv1.Build[i8Schema](func(s zapv1.Setter[i8Schema]) {
|
||||
zapv1.Write(s, i8Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, i8Fields.V); got != want {
|
||||
if got := zapv1.Read(view, i8Fields.V); got != want {
|
||||
t.Fatalf("int8: %d != %d", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Int16", func(t *testing.T) {
|
||||
const want int16 = -1234
|
||||
view, _ := zapv2.Build[i16Schema](func(s zapv2.Setter[i16Schema]) {
|
||||
zapv2.Write(s, i16Fields.V, want)
|
||||
view, _ := zapv1.Build[i16Schema](func(s zapv1.Setter[i16Schema]) {
|
||||
zapv1.Write(s, i16Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, i16Fields.V); got != want {
|
||||
if got := zapv1.Read(view, i16Fields.V); got != want {
|
||||
t.Fatalf("int16: %d != %d", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Int32", func(t *testing.T) {
|
||||
const want int32 = -7777777
|
||||
view, _ := zapv2.Build[i32Schema](func(s zapv2.Setter[i32Schema]) {
|
||||
zapv2.Write(s, i32Fields.V, want)
|
||||
view, _ := zapv1.Build[i32Schema](func(s zapv1.Setter[i32Schema]) {
|
||||
zapv1.Write(s, i32Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, i32Fields.V); got != want {
|
||||
if got := zapv1.Read(view, i32Fields.V); got != want {
|
||||
t.Fatalf("int32: %d != %d", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Int64", func(t *testing.T) {
|
||||
const want int64 = -(1 << 60)
|
||||
view, _ := zapv2.Build[i64Schema](func(s zapv2.Setter[i64Schema]) {
|
||||
zapv2.Write(s, i64Fields.V, want)
|
||||
view, _ := zapv1.Build[i64Schema](func(s zapv1.Setter[i64Schema]) {
|
||||
zapv1.Write(s, i64Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, i64Fields.V); got != want {
|
||||
if got := zapv1.Read(view, i64Fields.V); got != want {
|
||||
t.Fatalf("int64: %d != %d", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Uint32", func(t *testing.T) {
|
||||
const want uint32 = 0xdeadbeef
|
||||
view, _ := zapv2.Build[u32Schema](func(s zapv2.Setter[u32Schema]) {
|
||||
zapv2.Write(s, u32Fields.V, want)
|
||||
view, _ := zapv1.Build[u32Schema](func(s zapv1.Setter[u32Schema]) {
|
||||
zapv1.Write(s, u32Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, u32Fields.V); got != want {
|
||||
if got := zapv1.Read(view, u32Fields.V); got != want {
|
||||
t.Fatalf("uint32: %x != %x", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Float32", func(t *testing.T) {
|
||||
const want float32 = 3.14159
|
||||
view, _ := zapv2.Build[f32Schema](func(s zapv2.Setter[f32Schema]) {
|
||||
zapv2.Write(s, f32Fields.V, want)
|
||||
view, _ := zapv1.Build[f32Schema](func(s zapv1.Setter[f32Schema]) {
|
||||
zapv1.Write(s, f32Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, f32Fields.V); got != want {
|
||||
if got := zapv1.Read(view, f32Fields.V); got != want {
|
||||
t.Fatalf("float32: %v != %v", got, want)
|
||||
}
|
||||
})
|
||||
t.Run("Float64", func(t *testing.T) {
|
||||
const want float64 = 2.718281828459045
|
||||
view, _ := zapv2.Build[f64Schema](func(s zapv2.Setter[f64Schema]) {
|
||||
zapv2.Write(s, f64Fields.V, want)
|
||||
view, _ := zapv1.Build[f64Schema](func(s zapv1.Setter[f64Schema]) {
|
||||
zapv1.Write(s, f64Fields.V, want)
|
||||
})
|
||||
if got := zapv2.Read(view, f64Fields.V); got != want {
|
||||
if got := zapv1.Read(view, f64Fields.V); got != want {
|
||||
t.Fatalf("float64: %v != %v", got, want)
|
||||
}
|
||||
})
|
||||
@@ -152,8 +152,8 @@ func TestByteEqual_V1Canonical(t *testing.T) {
|
||||
func TestWrap_WrongKind(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, batchBuf := examples.NewAdvanceTime(7) // kind=1
|
||||
_, err := zapv2.Wrap[examples.BatchSchema](batchBuf)
|
||||
var sErr *zapv2.SchemaError
|
||||
_, err := zapv1.Wrap[examples.BatchSchema](batchBuf)
|
||||
var sErr *zapv1.SchemaError
|
||||
if !errors.As(err, &sErr) {
|
||||
t.Fatalf("expected SchemaError, got %T: %v", err, err)
|
||||
}
|
||||
@@ -170,14 +170,14 @@ func TestRegistry_Dispatch(t *testing.T) {
|
||||
const want uint64 = 42
|
||||
_, buf := examples.NewAdvanceTime(want)
|
||||
|
||||
kind, err := zapv2.PeekKind(buf)
|
||||
kind, err := zapv1.PeekKind(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("PeekKind: %v", err)
|
||||
}
|
||||
if kind != examples.KindAdvanceTime {
|
||||
t.Fatalf("PeekKind: got %v, want %v", kind, examples.KindAdvanceTime)
|
||||
}
|
||||
entry, ok := zapv2.DefaultRegistry.Lookup(kind)
|
||||
entry, ok := zapv1.DefaultRegistry.Lookup(kind)
|
||||
if !ok {
|
||||
t.Fatal("Registry: no entry for KindAdvanceTime")
|
||||
}
|
||||
@@ -188,11 +188,11 @@ func TestRegistry_Dispatch(t *testing.T) {
|
||||
t.Fatalf("entry.Wrap: %v", err)
|
||||
}
|
||||
// Final typed step.
|
||||
view, err := zapv2.WrapAs[examples.AdvanceTimeSchema](buf)
|
||||
view, err := zapv1.WrapAs[examples.AdvanceTimeSchema](buf)
|
||||
if err != nil {
|
||||
t.Fatalf("WrapAs: %v", err)
|
||||
}
|
||||
if got := zapv2.Read(view, examples.AdvanceTimeFields.Time); got != want {
|
||||
if got := zapv1.Read(view, examples.AdvanceTimeFields.Time); got != want {
|
||||
t.Fatalf("WrapAs round-trip: got %d, want %d", got, want)
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func TestPool_GenericGetPut(t *testing.T) {
|
||||
t.Parallel()
|
||||
type Box struct{ N int }
|
||||
created := 0
|
||||
pool := zapv2.NewPool(func() *Box {
|
||||
pool := zapv1.NewPool(func() *Box {
|
||||
created++
|
||||
return &Box{}
|
||||
})
|
||||
@@ -241,7 +241,7 @@ func TestList_RangeOverFunc(t *testing.T) {
|
||||
}
|
||||
view, _ := examples.NewBatch(7777, want)
|
||||
|
||||
if id := zapv2.Read(view, examples.BatchFields.ID); id != 7777 {
|
||||
if id := zapv1.Read(view, examples.BatchFields.ID); id != 7777 {
|
||||
t.Fatalf("BatchID: %d", id)
|
||||
}
|
||||
|
||||
@@ -254,8 +254,8 @@ func TestList_RangeOverFunc(t *testing.T) {
|
||||
got := []examples.Item{}
|
||||
for itemView := range list.All() {
|
||||
got = append(got, examples.Item{
|
||||
ID: zapv2.Read(itemView, examples.ItemFields.ID),
|
||||
Value: zapv2.Read(itemView, examples.ItemFields.Value),
|
||||
ID: zapv1.Read(itemView, examples.ItemFields.ID),
|
||||
Value: zapv1.Read(itemView, examples.ItemFields.Value),
|
||||
})
|
||||
}
|
||||
if len(got) != len(want) {
|
||||
@@ -270,7 +270,7 @@ func TestList_RangeOverFunc(t *testing.T) {
|
||||
// Indexed iteration.
|
||||
seen := 0
|
||||
for i, itemView := range list.Indexed() {
|
||||
if got, w := zapv2.Read(itemView, examples.ItemFields.ID), want[i].ID; got != w {
|
||||
if got, w := zapv1.Read(itemView, examples.ItemFields.ID), want[i].ID; got != w {
|
||||
t.Fatalf("Indexed item[%d].ID: %d, want %d", i, got, w)
|
||||
}
|
||||
seen++
|
||||
@@ -282,7 +282,7 @@ func TestList_RangeOverFunc(t *testing.T) {
|
||||
// At(i) direct access.
|
||||
for i, w := range want {
|
||||
v := list.At(i)
|
||||
if g := zapv2.Read(v, examples.ItemFields.ID); g != w.ID {
|
||||
if g := zapv1.Read(v, examples.ItemFields.ID); g != w.ID {
|
||||
t.Fatalf("At(%d).ID: %d, want %d", i, g, w.ID)
|
||||
}
|
||||
}
|
||||
@@ -308,8 +308,8 @@ func TestList_LargeIteration(t *testing.T) {
|
||||
sumID := uint64(0)
|
||||
sumValue := uint64(0)
|
||||
for itemView := range list.All() {
|
||||
sumID += zapv2.Read(itemView, examples.ItemFields.ID)
|
||||
sumValue += zapv2.Read(itemView, examples.ItemFields.Value)
|
||||
sumID += zapv1.Read(itemView, examples.ItemFields.ID)
|
||||
sumValue += zapv1.Read(itemView, examples.ItemFields.Value)
|
||||
}
|
||||
wantSumID := uint64(N) * uint64(N-1) / 2
|
||||
wantSumValue := wantSumID * 3
|
||||
@@ -336,23 +336,23 @@ func TestIter_Combinators(t *testing.T) {
|
||||
list := examples.Items(view)
|
||||
|
||||
// Take 3.
|
||||
first3 := zapv2.Collect(zapv2.Take(list.All(), 3))
|
||||
first3 := zapv1.Collect(zapv1.Take(list.All(), 3))
|
||||
if len(first3) != 3 {
|
||||
t.Fatalf("Take(3): got %d", len(first3))
|
||||
}
|
||||
|
||||
// Filter: only odd IDs.
|
||||
odd := zapv2.Filter(list.All(), func(v zapv2.View[examples.ItemSchema]) bool {
|
||||
return zapv2.Read(v, examples.ItemFields.ID)%2 == 1
|
||||
odd := zapv1.Filter(list.All(), func(v zapv1.View[examples.ItemSchema]) bool {
|
||||
return zapv1.Read(v, examples.ItemFields.ID)%2 == 1
|
||||
})
|
||||
if n := zapv2.Count(odd); n != 3 { // IDs 1, 3, 5
|
||||
if n := zapv1.Count(odd); n != 3 { // IDs 1, 3, 5
|
||||
t.Fatalf("Filter odd: %d, want 3", n)
|
||||
}
|
||||
|
||||
// Map: extract ID.
|
||||
ids := zapv2.Collect(zapv2.Map(list.All(),
|
||||
func(v zapv2.View[examples.ItemSchema]) uint64 {
|
||||
return zapv2.Read(v, examples.ItemFields.ID)
|
||||
ids := zapv1.Collect(zapv1.Map(list.All(),
|
||||
func(v zapv1.View[examples.ItemSchema]) uint64 {
|
||||
return zapv1.Read(v, examples.ItemFields.ID)
|
||||
}))
|
||||
if len(ids) != 5 || ids[0] != 1 || ids[4] != 5 {
|
||||
t.Fatalf("Map IDs: %v", ids)
|
||||
@@ -363,14 +363,14 @@ func TestIter_Combinators(t *testing.T) {
|
||||
// not panic on accessor calls.
|
||||
func TestIsZero(t *testing.T) {
|
||||
t.Parallel()
|
||||
var v zapv2.View[examples.AdvanceTimeSchema]
|
||||
var v zapv1.View[examples.AdvanceTimeSchema]
|
||||
if !v.IsZero() {
|
||||
t.Fatal("zero View should be IsZero")
|
||||
}
|
||||
if got := zapv2.Read(v, examples.AdvanceTimeFields.Time); got != 0 {
|
||||
if got := zapv1.Read(v, examples.AdvanceTimeFields.Time); got != 0 {
|
||||
t.Fatalf("zero View Read: got %d, want 0", got)
|
||||
}
|
||||
var l zapv2.List[examples.ItemSchema]
|
||||
var l zapv1.List[examples.ItemSchema]
|
||||
if !l.IsZero() {
|
||||
t.Fatal("zero List should be IsZero")
|
||||
}
|
||||
@@ -383,80 +383,80 @@ func TestIsZero(t *testing.T) {
|
||||
|
||||
type boolSchema struct{}
|
||||
|
||||
func (boolSchema) Kind() zapv2.KindByte { return 0xC0 }
|
||||
func (boolSchema) Kind() zapv1.KindByte { return 0xC0 }
|
||||
func (boolSchema) Size() int { return 2 }
|
||||
func (boolSchema) Name() string { return "boolSchema" }
|
||||
|
||||
var boolFields = struct {
|
||||
Flag zapv2.Field[boolSchema, bool]
|
||||
}{Flag: zapv2.At[boolSchema, bool](1)}
|
||||
Flag zapv1.Field[boolSchema, bool]
|
||||
}{Flag: zapv1.At[boolSchema, bool](1)}
|
||||
|
||||
type i8Schema struct{}
|
||||
|
||||
func (i8Schema) Kind() zapv2.KindByte { return 0xC1 }
|
||||
func (i8Schema) Kind() zapv1.KindByte { return 0xC1 }
|
||||
func (i8Schema) Size() int { return 2 }
|
||||
func (i8Schema) Name() string { return "i8Schema" }
|
||||
|
||||
var i8Fields = struct {
|
||||
V zapv2.Field[i8Schema, int8]
|
||||
}{V: zapv2.At[i8Schema, int8](1)}
|
||||
V zapv1.Field[i8Schema, int8]
|
||||
}{V: zapv1.At[i8Schema, int8](1)}
|
||||
|
||||
type i16Schema struct{}
|
||||
|
||||
func (i16Schema) Kind() zapv2.KindByte { return 0xC2 }
|
||||
func (i16Schema) Kind() zapv1.KindByte { return 0xC2 }
|
||||
func (i16Schema) Size() int { return 4 }
|
||||
func (i16Schema) Name() string { return "i16Schema" }
|
||||
|
||||
var i16Fields = struct {
|
||||
V zapv2.Field[i16Schema, int16]
|
||||
}{V: zapv2.At[i16Schema, int16](2)}
|
||||
V zapv1.Field[i16Schema, int16]
|
||||
}{V: zapv1.At[i16Schema, int16](2)}
|
||||
|
||||
type i32Schema struct{}
|
||||
|
||||
func (i32Schema) Kind() zapv2.KindByte { return 0xC3 }
|
||||
func (i32Schema) Kind() zapv1.KindByte { return 0xC3 }
|
||||
func (i32Schema) Size() int { return 8 }
|
||||
func (i32Schema) Name() string { return "i32Schema" }
|
||||
|
||||
var i32Fields = struct {
|
||||
V zapv2.Field[i32Schema, int32]
|
||||
}{V: zapv2.At[i32Schema, int32](4)}
|
||||
V zapv1.Field[i32Schema, int32]
|
||||
}{V: zapv1.At[i32Schema, int32](4)}
|
||||
|
||||
type i64Schema struct{}
|
||||
|
||||
func (i64Schema) Kind() zapv2.KindByte { return 0xC4 }
|
||||
func (i64Schema) Kind() zapv1.KindByte { return 0xC4 }
|
||||
func (i64Schema) Size() int { return 16 }
|
||||
func (i64Schema) Name() string { return "i64Schema" }
|
||||
|
||||
var i64Fields = struct {
|
||||
V zapv2.Field[i64Schema, int64]
|
||||
}{V: zapv2.At[i64Schema, int64](8)}
|
||||
V zapv1.Field[i64Schema, int64]
|
||||
}{V: zapv1.At[i64Schema, int64](8)}
|
||||
|
||||
type u32Schema struct{}
|
||||
|
||||
func (u32Schema) Kind() zapv2.KindByte { return 0xC5 }
|
||||
func (u32Schema) Kind() zapv1.KindByte { return 0xC5 }
|
||||
func (u32Schema) Size() int { return 8 }
|
||||
func (u32Schema) Name() string { return "u32Schema" }
|
||||
|
||||
var u32Fields = struct {
|
||||
V zapv2.Field[u32Schema, uint32]
|
||||
}{V: zapv2.At[u32Schema, uint32](4)}
|
||||
V zapv1.Field[u32Schema, uint32]
|
||||
}{V: zapv1.At[u32Schema, uint32](4)}
|
||||
|
||||
type f32Schema struct{}
|
||||
|
||||
func (f32Schema) Kind() zapv2.KindByte { return 0xC6 }
|
||||
func (f32Schema) Kind() zapv1.KindByte { return 0xC6 }
|
||||
func (f32Schema) Size() int { return 8 }
|
||||
func (f32Schema) Name() string { return "f32Schema" }
|
||||
|
||||
var f32Fields = struct {
|
||||
V zapv2.Field[f32Schema, float32]
|
||||
}{V: zapv2.At[f32Schema, float32](4)}
|
||||
V zapv1.Field[f32Schema, float32]
|
||||
}{V: zapv1.At[f32Schema, float32](4)}
|
||||
|
||||
type f64Schema struct{}
|
||||
|
||||
func (f64Schema) Kind() zapv2.KindByte { return 0xC7 }
|
||||
func (f64Schema) Kind() zapv1.KindByte { return 0xC7 }
|
||||
func (f64Schema) Size() int { return 16 }
|
||||
func (f64Schema) Name() string { return "f64Schema" }
|
||||
|
||||
var f64Fields = struct {
|
||||
V zapv2.Field[f64Schema, float64]
|
||||
}{V: zapv2.At[f64Schema, float64](8)}
|
||||
V zapv1.Field[f64Schema, float64]
|
||||
}{V: zapv1.At[f64Schema, float64](8)}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package zapv2
|
||||
package zapv1
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
@@ -153,7 +153,7 @@ func (m *Message) Version() uint16 {
|
||||
// ParseHeader validates a ZAP wire frame and returns the (validated
|
||||
// data slice, root offset) WITHOUT allocating a [*Message]. Same checks
|
||||
// as [Parse] — magic, version, size — but the result is two values, not
|
||||
// a pointer. Intended for generic wrappers (zapv2) that build their own
|
||||
// a pointer. Intended for generic wrappers (zapv1) that build their own
|
||||
// value-typed accessors and never need a *Message.
|
||||
//
|
||||
// Returns (data[:size], rootOff, nil) on success.
|
||||
@@ -162,7 +162,7 @@ func (m *Message) Version() uint16 {
|
||||
// size + bounds). The implementation is intentionally written as one
|
||||
// linear sequence (no intermediate function calls) so the inliner
|
||||
// folds the whole body into the caller. Combined with the value-
|
||||
// typed [zapv2.View], this is what makes the v2 read path match v1's
|
||||
// typed [zapv1.View], this is what makes the v2 read path match v1's
|
||||
// 2 ns hand-rolled per-Read cost — zero function calls, zero heap.
|
||||
func ParseHeader(data []byte) ([]byte, int, error) {
|
||||
return parseHeaderImpl(data)
|
||||
@@ -206,7 +206,7 @@ func WrapBuffer(data []byte) *Message {
|
||||
}
|
||||
|
||||
// RootObjectAt returns a [zap.Object] anchored at absolute offset
|
||||
// `off` within this message. Used by zapv2.Build to avoid a redundant
|
||||
// `off` within this message. Used by zapv1.Build to avoid a redundant
|
||||
// header-read after [Builder.FinishAsRoot] already returned the root
|
||||
// position.
|
||||
func (m *Message) RootObjectAt(off int) Object {
|
||||
@@ -281,7 +281,7 @@ func (o Object) IsNull() bool {
|
||||
}
|
||||
|
||||
// Offset returns the object's absolute byte offset within its
|
||||
// underlying message. Exposed so external generic wrappers (zapv2)
|
||||
// underlying message. Exposed so external generic wrappers (zapv1)
|
||||
// can construct typed sub-views into the same buffer without
|
||||
// re-walking the parent pointers.
|
||||
//
|
||||
@@ -294,7 +294,7 @@ func (o Object) Offset() int {
|
||||
}
|
||||
|
||||
// Message returns the underlying [*Message] this Object is a view
|
||||
// into. Used by zapv2 to alias the message's bytes for direct
|
||||
// into. Used by zapv1 to alias the message's bytes for direct
|
||||
// payload indexing.
|
||||
func (o Object) Message() *Message {
|
||||
return o.msg
|
||||
|
||||
Reference in New Issue
Block a user