bitread
import bitread from "bitread";
// An ADTS header starts with 12 bits of sync word, then 1 bit of MPEG version
let frame: []const u8 = "\xFF\xF1\x50\x80";
var r: bitread.Reader = bitread.reader(frame);
let sync: i64 = r.read(12); // 0xFFF
let version: i64 = r.read(1); // 0: MPEG-4
r.skip(3); // layer, protection_absent
let profile: i64 = r.read(2); // 1: AAC-LC
if (r.bad) { /* the header was cut short */ }bitread reads bits most significant first: the first bit of a byte
is its highest. That is the order AAC, H.264, MP4’s descriptors and most
media formats use; deflate and brotli read the other way round, with
lz’s BitIn. aac, h264 and
mp4 are built on it.
bitread is a pure module, freestanding (t0): nothing allocates.
peek
pub fn peek(d: []const u8, pos: i64, n: i64) -> i64The n bits of d starting at bit pos (bit 0 is the highest bit of
d[0]), as a number whose highest bit is the first one read. Bits past
the end of d read as zeros, so a decoder can look ahead at the longest
code it knows without checking how much is left.
let d: []const u8 = "\xA5\x0F";
bitread.peek(d, 0, 4); // 0xA
bitread.peek(d, 4, 8); // 0x50
bitread.peek(d, 12, 8); // 0xF0: the last four bits are past the endn is 0 to 57. It traps when n is outside that range or pos is
negative.
Reader
pub struct Reader { d: []const u8; pos: i64; end: i64; bad: bool; }
pub fn reader(d: []const u8) -> ReaderA position in a buffer: pos counts bits from the start, end is where
the data ends (d.len * 8). Reading past the end does not trap: the
missing bits are zeros and bad becomes true and stays true. Read a
whole unit (a header, a block) and check bad once at the end.
| Method | What it does |
|---|---|
r.peek(n) | The next n bits (0..57), without moving |
r.read(n) | The next n bits (0..57), taken |
r.skip(n) | Moves n bits on |
r.align() | Moves on to the next byte boundary; nothing when at one |
r.left() | The bits left: end - pos (negative after reading past the end) |
peek, read and skip are inlined: use them in decoding loops.
ErrMsg
pub struct ErrMsg { buf: [200]u8; len: i64; }
pub fn ErrMsg.set(*self, what: []const u8)
pub fn ErrMsg.text(*const self) -> []const u8The text of a codec’s last error, kept without a heap: set keeps the
first 200 bytes of what, text returns them (empty before any set).
A decoder returns an error enum and keeps the details here, for a
last_error() method:
pub struct Decoder { err: bitread.ErrMsg; }
fn Decoder.fail(*self, e: MyError, what: []const u8) -> MyError {
self.err.set(what);
return e;
}
pub fn Decoder.last_error(*const self) -> []const u8 { return self.err.text(); }Last modified: