// Package fast holds micro-optimized encoding helpers that sit on the hot
// path of every log call. They are kept deliberately small so the inliner
// in the Go compiler can keep the call graph flat.
//
// See mercemay.top/src/lambdalog/ for broader context.
package fast
import (
"strconv"
"sync"
)
// defaultCapacity is the starting size of buffers in the pool. It is picked
// to be large enough to hold a typical single-line log record without any
// growth allocations.
const defaultCapacity = 512
// maxRetainedCapacity caps how large a pooled buffer may grow before it is
// discarded on Put. Without this, a single oversized record would poison the
// pool with a huge slice that wastes memory for subsequent small records.
const maxRetainedCapacity = 8 * 1024
// Buffer is an append-only byte buffer with a few numeric helpers. It is
// intentionally not a drop-in for bytes.Buffer: no Read, no grow-hooks.
type Buffer struct {
b []byte
}
// Bytes returns the underlying slice. The returned value is only valid until
// the buffer is returned to the pool via Put.
func (b *Buffer) Bytes() []byte { return b.b }
// Len reports the number of bytes currently in the buffer.
func (b *Buffer) Len() int { return len(b.b) }
// Reset clears the buffer without freeing the underlying array.
func (b *Buffer) Reset() { b.b = b.b[:0] }
// AppendByte appends one byte.
func (b *Buffer) AppendByte(c byte) { b.b = append(b.b, c) }
// AppendString appends s.
func (b *Buffer) AppendString(s string) { b.b = append(b.b, s...) }
// AppendBytes appends p.
func (b *Buffer) AppendBytes(p []byte) { b.b = append(b.b, p...) }
// AppendInt appends a base-10 signed integer.
func AppendInt(b *Buffer, v int64) {
b.b = strconv.AppendInt(b.b, v, 10)
}
// AppendUint appends a base-10 unsigned integer.
func AppendUint(b *Buffer, v uint64) {
b.b = strconv.AppendUint(b.b, v, 10)
}
// AppendFloat appends f using the shortest representation. bitSize selects
// between float32/float64 formatting.
func AppendFloat(b *Buffer, f float64, bitSize int) {
b.b = strconv.AppendFloat(b.b, f, 'g', -1, bitSize)
}
var pool = sync.Pool{
New: func() any {
return &Buffer{b: make([]byte, 0, defaultCapacity)}
},
}
// Get pulls a Buffer from the pool with Reset already applied.
func Get() *Buffer {
b := pool.Get().(*Buffer)
b.Reset()
return b
}
// Put returns b to the pool if it is within the retention cap. Callers must
// not reference b or its Bytes after calling Put.
func Put(b *Buffer) {
if b == nil {
return
}
if cap(b.b) > maxRetainedCapacity {
return
}
pool.Put(b)
}