bits

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader reads bits from a byte buffer. It exposes two API tiers:

  • Fast tier (no "Read" prefix): never returns an error. Reads past the end of the buffer are zero-filled/clamped and recorded via Overrun. Intended for hot decode loops.
  • Checked tier ("Read" prefix): thin wrappers around the Fast tier that surface Overrun as an error. Intended for cold paths (header parsing) where a precise per-call error is worth the branch.

func New

func New(data []byte) *Reader

New creates a Reader over data, starting at bit position 0.

func (*Reader) Bit

func (r *Reader) Bit() uint8

Bit reads a single bit (0 or 1). Past the limit it sets Overrun and returns 0. It returns uint8 rather than bool so Bits64/Unary64/Signed32 can accumulate it with a branchless shift-or instead of a conditional.

func (*Reader) Bits32

func (r *Reader) Bits32(width uint8) uint32

Bits32 reads a width up to 32 bits using a byte-cache algorithm ported unchanged from MP3's original GetBits (used by codec-mp3's layer1/2 dequantization hot path). It is not decomposed into Bit, since doing so would change the performance characteristics MP3 currently relies on.

func (*Reader) Bits64

func (r *Reader) Bits64(width uint8) uint64

Bits64 reads width bits (width <= 64) MSB-first.

func (*Reader) Byte

func (r *Reader) Byte() uint8

Byte reads one byte at the current (byte-aligned) position. Alignment is a caller invariant, not a data-driven condition, so it is checked via assertf rather than returned as an error.

func (*Reader) ByteAt

func (r *Reader) ByteAt(pos int) uint32

ByteAt returns the byte at index pos, or 0 if pos is out of range. It is the bounds-checked primitive shared by Bit/Byte/Bits32 and by MP3's Huffman decoding hot path.

func (*Reader) BytePos

func (r *Reader) BytePos() int

BytePos returns the current position rounded up to the next byte.

func (*Reader) Init

func (r *Reader) Init(buffer []byte, position int32, limit int32)

Init (re)initializes the reader without allocating, so it can be reused across frames.

func (*Reader) Overrun

func (r *Reader) Overrun() bool

the limit. It is a sticky flag reset by Init/New: since the read position only advances, once it goes true every later read is also out of range, so a single check after a batch of Fast-tier reads is equivalent to checking every individual call.

func (*Reader) Position

func (r *Reader) Position() int32

Position returns the current bit position.

func (*Reader) ReadBit

func (r *Reader) ReadBit() (uint8, error)

ReadBit is the Checked-tier wrapper around Bit.

func (*Reader) ReadBits32

func (r *Reader) ReadBits32(width uint8) (uint32, error)

ReadBits32 is the Checked-tier wrapper around Bits32.

func (*Reader) ReadBits64

func (r *Reader) ReadBits64(width uint8) (uint64, error)

ReadBits64 is the Checked-tier wrapper around Bits64.

func (*Reader) ReadByte

func (r *Reader) ReadByte() (byte, error)

ReadByte is the Checked-tier wrapper around Byte, named to match Go's io.ByteReader convention (e.g. bufio.Reader.ReadByte).

func (*Reader) ReadSigned32

func (r *Reader) ReadSigned32(width uint8) (int32, error)

ReadSigned32 is the Checked-tier wrapper around Signed32.

func (*Reader) ReadSigned64

func (r *Reader) ReadSigned64(width uint8) (int64, error)

ReadSigned64 is the Checked-tier wrapper around Signed64.

func (*Reader) ReadUnary64

func (r *Reader) ReadUnary64() (uint64, error)

ReadUnary64 is the Checked-tier wrapper around Unary64.

func (*Reader) Remaining

func (r *Reader) Remaining() int32

Remaining returns the number of unread bits between the current position and the limit.

func (*Reader) Rice64

func (r *Reader) Rice64(param uint8) uint64

Rice64 reads a unary quotient followed by param remainder bits.

func (*Reader) Seek

func (r *Reader) Seek(pos int32)

Seek jumps to an absolute bit position. It exists for the one place that needs it (Huffman decoding aligning to a granule's declared bit boundary), not as a general-purpose field setter.

func (*Reader) Signed32

func (r *Reader) Signed32(width uint8) int32

Signed32 reads width bits (width in [1, 32]) and sign-extends the result.

func (*Reader) Signed64

func (r *Reader) Signed64(width uint8) int64

Signed64 reads width bits (width in [1, 64]) and sign-extends the result.

func (*Reader) SkipToByte

func (r *Reader) SkipToByte()

SkipToByte advances the position to the next byte boundary without reading a value. This is a distinct operation from Byte/ReadByte (which read a byte), kept separate so the two are never confused for one another.

func (*Reader) Unary64

func (r *Reader) Unary64() uint64

Unary64 reads a unary-coded value: the number of 0 bits before the next 1 bit. It stops at the limit instead of looping forever on truncated data.

The scan runs in three phases using math/bits.LeadingZeros: (1) inspect the remainder of an unaligned first byte, (2) fast-scan whole words then bytes that are fully within both the limit and the physical buffer, (3) finish the remaining (<8-bit) tail with the bit-at-a-time path, which also supplies the sticky-overrun bookkeeping on truncated data.

func (*Reader) Unread

func (r *Reader) Unread() []byte

Unread returns the unread byte slice between the current (byte-aligned) position and the limit.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer writes MSB-first bits to an in-memory byte buffer.

func NewWriter

func NewWriter() *Writer

NewWriter creates an empty bit writer.

func (*Writer) Bit

func (w *Writer) Bit(value uint8)

Bit writes a single bit. Any non-zero value is encoded as 1.

func (*Writer) Bits64

func (w *Writer) Bits64(value uint64, width uint8)

Bits64 writes width bits (width <= 64) MSB-first from value. It merges into the in-progress last byte once (if the writer isn't byte-aligned), appends any whole bytes directly, and appends one final partial byte — replacing what used to be `width` separate per-bit calls, each with its own division/modulo and append-growth check.

func (*Writer) Byte

func (w *Writer) Byte(value byte)

Byte writes one byte at the current byte-aligned position.

func (*Writer) BytePos

func (w *Writer) BytePos() int

BytePos returns the current position rounded up to the next byte.

func (*Writer) Bytes

func (w *Writer) Bytes() []byte

Bytes returns the bytes written so far. If the writer is not byte-aligned, the final byte contains zero padding in the remaining least-significant bits.

func (*Writer) BytesAppend

func (w *Writer) BytesAppend(values []byte)

BytesAppend writes bytes at the current byte-aligned position.

func (*Writer) DetachBytes

func (w *Writer) DetachBytes() []byte

DetachBytes transfers the written buffer to the caller and resets the writer. The returned bytes must not be retained by the writer's caller after transfer.

func (*Writer) Grow

func (w *Writer) Grow(n int)

Grow ensures space for n more bytes without another allocation.

func (*Writer) Init

func (w *Writer) Init()

Init resets the writer to an empty buffer, retaining capacity for reuse.

func (*Writer) PadToByte

func (w *Writer) PadToByte()

PadToByte writes zero bits until the next byte boundary.

func (*Writer) Position

func (w *Writer) Position() int32

Position returns the current bit position.

func (*Writer) Signed64

func (w *Writer) Signed64(value int64, width uint8)

Signed64 writes width bits (width <= 64) as a two's-complement signed value.

func (*Writer) Unary64

func (w *Writer) Unary64(value uint64)

Unary64 writes a unary-coded value: value zero bits followed by a one bit. Rice-coded residuals (its main caller) are dominated by this: each sample writes one unary quotient, so batching the zero run into whole-byte appends instead of `value` separate per-bit calls matters even when the typical run is short.

func (*Writer) UnaryBits64

func (w *Writer) UnaryBits64(value uint64, width uint8)

UnaryBits64 writes a unary-prefixed bit-field: value>>width zero bits, then a one bit, then the low width bits of value. It is equivalent to Unary64(value>>width) followed by Bits64(value, width) — the pattern each Rice-coded residual sample uses — but folds both into a single Bits64 call when the combined field fits in 64 bits (the common case once the Rice parameter is well chosen), instead of two separate alignment/append passes per sample.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL