From 1d84127ff1c3f5b3130c4f3d28dd9a0a7e82f6e9 Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Thu, 5 Mar 2026 09:50:59 -0700 Subject: [PATCH 1/2] Add cursor helpers --- pkg/internal/largebuf/large_buffer.go | 117 ++++++++++++ pkg/internal/largebuf/large_buffer_test.go | 199 +++++++++++++++++++++ 2 files changed, 316 insertions(+) diff --git a/pkg/internal/largebuf/large_buffer.go b/pkg/internal/largebuf/large_buffer.go index 5c301ccddb..96703b494c 100644 --- a/pkg/internal/largebuf/large_buffer.go +++ b/pkg/internal/largebuf/large_buffer.go @@ -543,6 +543,123 @@ func (r *LargeBufferReader) Bytes() []byte { return b } +// ── Cursor-based scalar helpers ─────────────────────────────────────────────── +// +// Each helper reads a fixed-width integer at the current cursor position and advances it. +// All delegate to ReadN: zero-copy within a chunk, scratch-backed across boundaries. + +// ReadU8 reads a uint8 at the current cursor position. +func (r *LargeBufferReader) ReadU8() (uint8, error) { + b, err := r.ReadN(1) + if err != nil { + return 0, err + } + + return b[0], nil +} + +// ReadU16BE reads a big-endian uint16 at the current cursor position. +func (r *LargeBufferReader) ReadU16BE() (uint16, error) { + b, err := r.ReadN(2) + if err != nil { + return 0, err + } + + return binary.BigEndian.Uint16(b), nil +} + +// ReadI16BE reads a big-endian int16 at the current cursor position. +func (r *LargeBufferReader) ReadI16BE() (int16, error) { + v, err := r.ReadU16BE() + + return int16(v), err +} + +// ReadU32BE reads a big-endian uint32 at the current cursor position. +func (r *LargeBufferReader) ReadU32BE() (uint32, error) { + b, err := r.ReadN(4) + if err != nil { + return 0, err + } + + return binary.BigEndian.Uint32(b), nil +} + +// ReadI32BE reads a big-endian int32 at the current cursor position. +func (r *LargeBufferReader) ReadI32BE() (int32, error) { + v, err := r.ReadU32BE() + + return int32(v), err +} + +// ReadU64BE reads a big-endian uint64 at the current cursor position. +func (r *LargeBufferReader) ReadU64BE() (uint64, error) { + b, err := r.ReadN(8) + if err != nil { + return 0, err + } + + return binary.BigEndian.Uint64(b), nil +} + +// ReadI64BE reads a big-endian int64 at the current cursor position. +func (r *LargeBufferReader) ReadI64BE() (int64, error) { + v, err := r.ReadU64BE() + + return int64(v), err +} + +// ReadU16LE reads a little-endian uint16 at the current cursor position. +func (r *LargeBufferReader) ReadU16LE() (uint16, error) { + b, err := r.ReadN(2) + if err != nil { + return 0, err + } + + return binary.LittleEndian.Uint16(b), nil +} + +// ReadI16LE reads a little-endian int16 at the current cursor position. +func (r *LargeBufferReader) ReadI16LE() (int16, error) { + v, err := r.ReadU16LE() + + return int16(v), err +} + +// ReadU32LE reads a little-endian uint32 at the current cursor position. +func (r *LargeBufferReader) ReadU32LE() (uint32, error) { + b, err := r.ReadN(4) + if err != nil { + return 0, err + } + + return binary.LittleEndian.Uint32(b), nil +} + +// ReadI32LE reads a little-endian int32 at the current cursor position. +func (r *LargeBufferReader) ReadI32LE() (int32, error) { + v, err := r.ReadU32LE() + + return int32(v), err +} + +// ReadU64LE reads a little-endian uint64 at the current cursor position. +func (r *LargeBufferReader) ReadU64LE() (uint64, error) { + b, err := r.ReadN(8) + if err != nil { + return 0, err + } + + return binary.LittleEndian.Uint64(b), nil +} + +// ReadI64LE reads a little-endian int64 at the current cursor position. +func (r *LargeBufferReader) ReadI64LE() (int64, error) { + v, err := r.ReadU64LE() + + return int64(v), err +} + // copyN copies exactly len(dst) bytes from the current read position into dst, advancing the // cursor. Assumes the caller has already verified that len(dst) <= r.Remaining(). func (r *LargeBufferReader) copyN(dst []byte) { diff --git a/pkg/internal/largebuf/large_buffer_test.go b/pkg/internal/largebuf/large_buffer_test.go index 4e1642d03a..e052e02ef4 100644 --- a/pkg/internal/largebuf/large_buffer_test.go +++ b/pkg/internal/largebuf/large_buffer_test.go @@ -974,6 +974,205 @@ func TestCursorUnchanged_byAbsoluteOffsetMethods(t *testing.T) { assert.Equal(t, before, r.ReadOffset(), "U32LEAt must not move cursor") } +// ── Cursor-based scalar helpers ─────────────────────────────────────────────── + +func TestReaderScalarBE_withinSingleChunk(t *testing.T) { + // Sequential layout: U8 | U16BE | U32BE | U64BE | I16BE | I32BE | I64BE + data := []byte{ + 0x42, + 0x01, 0x02, + 0x01, 0x02, 0x03, 0x04, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, + 0x01, 0x02, 0x03, 0x04, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + } + lb := NewLargeBufferFrom(data) + r := lb.NewReader() + + u8, err := r.ReadU8() + require.NoError(t, err) + assert.Equal(t, uint8(0x42), u8) + + u16, err := r.ReadU16BE() + require.NoError(t, err) + assert.Equal(t, uint16(0x0102), u16) + + u32, err := r.ReadU32BE() + require.NoError(t, err) + assert.Equal(t, uint32(0x01020304), u32) + + u64, err := r.ReadU64BE() + require.NoError(t, err) + assert.Equal(t, uint64(0x0102030405060708), u64) + + i16, err := r.ReadI16BE() + require.NoError(t, err) + assert.Equal(t, int16(0x0102), i16) + + i32, err := r.ReadI32BE() + require.NoError(t, err) + assert.Equal(t, int32(0x01020304), i32) + + i64, err := r.ReadI64BE() + require.NoError(t, err) + assert.Equal(t, int64(0x0102030405060708), i64) + + assert.Equal(t, 0, r.Remaining()) +} + +func TestReaderScalarBE_crossChunkBoundary(t *testing.T) { + lb := NewLargeBuffer() + lb.AppendChunk([]byte{0x01, 0x02}) + lb.AppendChunk([]byte{0x03, 0x04, 0x05, 0x06, 0x07, 0x08}) + + r := lb.NewReader() + + u32, err := r.ReadU32BE() + require.NoError(t, err) + assert.Equal(t, uint32(0x01020304), u32) + + r.Reset() + u64, err := r.ReadU64BE() + require.NoError(t, err) + assert.Equal(t, uint64(0x0102030405060708), u64) +} + +func TestReaderScalarBE_signedNegativeValues(t *testing.T) { + lb := NewLargeBufferFrom(bytes.Repeat([]byte{0xFF}, 14)) // 2+4+8 bytes + r := lb.NewReader() + + i16, err := r.ReadI16BE() + require.NoError(t, err) + assert.Equal(t, int16(-1), i16) + + i32, err := r.ReadI32BE() + require.NoError(t, err) + assert.Equal(t, int32(-1), i32) + + i64, err := r.ReadI64BE() + require.NoError(t, err) + assert.Equal(t, int64(-1), i64) +} + +func TestReaderScalarLE_withinSingleChunk(t *testing.T) { + // Sequential layout: U16LE | U32LE | U64LE | I16LE | I32LE | I64LE + data := []byte{ + 0x02, 0x01, + 0x04, 0x03, 0x02, 0x01, + 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, + 0x02, 0x01, + 0x04, 0x03, 0x02, 0x01, + 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, + } + lb := NewLargeBufferFrom(data) + r := lb.NewReader() + + u16, err := r.ReadU16LE() + require.NoError(t, err) + assert.Equal(t, uint16(0x0102), u16) + + u32, err := r.ReadU32LE() + require.NoError(t, err) + assert.Equal(t, uint32(0x01020304), u32) + + u64, err := r.ReadU64LE() + require.NoError(t, err) + assert.Equal(t, uint64(0x0102030405060708), u64) + + i16, err := r.ReadI16LE() + require.NoError(t, err) + assert.Equal(t, int16(0x0102), i16) + + i32, err := r.ReadI32LE() + require.NoError(t, err) + assert.Equal(t, int32(0x01020304), i32) + + i64, err := r.ReadI64LE() + require.NoError(t, err) + assert.Equal(t, int64(0x0102030405060708), i64) + + assert.Equal(t, 0, r.Remaining()) +} + +func TestReaderScalarLE_crossChunkBoundary(t *testing.T) { + lb := NewLargeBuffer() + lb.AppendChunk([]byte{0x04, 0x03}) + lb.AppendChunk([]byte{0x02, 0x01, 0x08, 0x07, 0x06, 0x05}) + + r := lb.NewReader() + + u32, err := r.ReadU32LE() + require.NoError(t, err) + assert.Equal(t, uint32(0x01020304), u32) + + r.Reset() + u64, err := r.ReadU64LE() + require.NoError(t, err) + assert.Equal(t, uint64(0x0506070801020304), u64) +} + +func TestReaderScalarLE_signedNegativeValues(t *testing.T) { + lb := NewLargeBufferFrom(bytes.Repeat([]byte{0xFF}, 14)) // 2+4+8 bytes + r := lb.NewReader() + + i16, err := r.ReadI16LE() + require.NoError(t, err) + assert.Equal(t, int16(-1), i16) + + i32, err := r.ReadI32LE() + require.NoError(t, err) + assert.Equal(t, int32(-1), i32) + + i64, err := r.ReadI64LE() + require.NoError(t, err) + assert.Equal(t, int64(-1), i64) +} + +func TestReaderScalar_advancesCursor(t *testing.T) { + lb := NewLargeBufferFrom(bytes.Repeat([]byte{0x00}, 16)) + r := lb.NewReader() + + assert.Equal(t, 16, r.Remaining()) + _, _ = r.ReadU8() + assert.Equal(t, 15, r.Remaining()) + _, _ = r.ReadU16BE() + assert.Equal(t, 13, r.Remaining()) + _, _ = r.ReadU32BE() + assert.Equal(t, 9, r.Remaining()) + _, _ = r.ReadU64BE() + assert.Equal(t, 1, r.Remaining()) +} + +func TestReaderScalar_tooShort_returnsError(t *testing.T) { + lb := NewLargeBufferFrom([]byte{0x01, 0x02}) + r := lb.NewReader() + + _, _ = r.ReadU16BE() // consume all bytes + + _, err := r.ReadU8() + require.Error(t, err) + + r.Reset() + _, _ = r.ReadU8() + _, err = r.ReadU16BE() // only 1 byte left + require.Error(t, err) +} + +func TestReaderScalar_zeroAllocs(t *testing.T) { + lb := NewLargeBufferFrom(bytes.Repeat([]byte{0x01}, 64)) + r := lb.NewReader() + + allocs := testing.AllocsPerRun(1000, func() { + r.Reset() + for r.Remaining() >= 4 { + _, _ = r.ReadU32BE() + } + }) + + assert.InDelta(t, float64(0), allocs, 0, "cursor scalar reads within a single chunk must be zero-alloc") +} + // ── Zero-alloc verification for hot path ───────────────────────────────────── func TestReadN_singleChunk_zeroAllocsWithBinaryDecode(t *testing.T) { From 9457c4a2722d3cd1cf56adf355589ea8d6c5e48b Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Thu, 5 Mar 2026 11:21:15 -0700 Subject: [PATCH 2/2] Review feedback --- pkg/internal/largebuf/large_buffer_test.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/internal/largebuf/large_buffer_test.go b/pkg/internal/largebuf/large_buffer_test.go index e052e02ef4..11a6965016 100644 --- a/pkg/internal/largebuf/large_buffer_test.go +++ b/pkg/internal/largebuf/large_buffer_test.go @@ -1134,13 +1134,17 @@ func TestReaderScalar_advancesCursor(t *testing.T) { r := lb.NewReader() assert.Equal(t, 16, r.Remaining()) - _, _ = r.ReadU8() + _, err := r.ReadU8() + require.NoError(t, err) assert.Equal(t, 15, r.Remaining()) - _, _ = r.ReadU16BE() + _, err = r.ReadU16BE() + require.NoError(t, err) assert.Equal(t, 13, r.Remaining()) - _, _ = r.ReadU32BE() + _, err = r.ReadU32BE() + require.NoError(t, err) assert.Equal(t, 9, r.Remaining()) - _, _ = r.ReadU64BE() + _, err = r.ReadU64BE() + require.NoError(t, err) assert.Equal(t, 1, r.Remaining()) } @@ -1162,15 +1166,21 @@ func TestReaderScalar_tooShort_returnsError(t *testing.T) { func TestReaderScalar_zeroAllocs(t *testing.T) { lb := NewLargeBufferFrom(bytes.Repeat([]byte{0x01}, 64)) r := lb.NewReader() + // lastErr is declared outside the closure so require.NoError can be called + // after AllocsPerRun as calling it inside the closure would itself allocate. + var lastErr error allocs := testing.AllocsPerRun(1000, func() { r.Reset() for r.Remaining() >= 4 { - _, _ = r.ReadU32BE() + if _, lastErr = r.ReadU32BE(); lastErr != nil { + break + } } }) - assert.InDelta(t, float64(0), allocs, 0, "cursor scalar reads within a single chunk must be zero-alloc") + require.NoError(t, lastErr) + assert.Zero(t, allocs, "cursor scalar reads within a single chunk must be zero-alloc") } // ── Zero-alloc verification for hot path ─────────────────────────────────────