# buffer-utils _(no submodules)_ ## Purpose Provides a compact set of pure binary-reading helpers that operate directly on `Uint8Array` values. These utilities abstract away the bit-shifting and byte-ordering arithmetic that every audio-format parser needs, reducing the risk of off-by-one errors and making parser code easier to read and test in isolation. All helpers are environment-agnostic — they use only the `Uint8Array` and `TextDecoder` web-standard APIs, so they work identically in Node.js 18+, Deno, and modern browsers without any polyfills. ## Features - Unsigned/signed integer readers: `readUint8`, `readUint16BE`, `readUint16LE`, `readUint32BE`, `readUint32LE`, `readInt32BE` - String decoder with `"utf8"` (TextDecoder) and `"latin1"` (char-code loop) encodings - `readSyncsafeInt` for ID3v2 syncsafe 28-bit integers - `concatBuffers` for building test fixtures and merging partial reads - Every function returns a sensible default (`0` / `""`) on out-of-bounds access rather than throwing ## Usage: Basic Example ```ts import { readUint32BE, readString, } from "@suaveplan/audio-metadata"; const buf = new Uint8Array([0x00, 0x00, 0x04, 0x00]); const size = readUint32BE(buf, 0); // 1024 const text = new Uint8Array([0x48, 0x69]); readString(text, 0, 2); // "Hi" ``` ## Usage: Advanced Example ```ts import { readSyncsafeInt, readUint16BE, concatBuffers, } from "@suaveplan/audio-metadata"; // Decode an ID3v2 tag size from a header const header = new Uint8Array([0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01]); const tagSize = readSyncsafeInt(header, 6); // 257 // Build a larger test buffer by concatenating parts const part1 = new Uint8Array([0x52, 0x49, 0x46, 0x46]); const part2 = new Uint8Array([0x00, 0x10, 0x00, 0x00]); const combined = concatBuffers(part1, part2); // "RIFF" + size bytes ``` ## API Reference ### `readUint8(buf, offset)` Returns `buf[offset]` as a number (0–255), or `0` if out of bounds. ### `readUint16BE(buf, offset)` Reads two bytes at `offset` as a big-endian unsigned 16-bit integer. ### `readUint16LE(buf, offset)` Reads two bytes at `offset` as a little-endian unsigned 16-bit integer. ### `readUint32BE(buf, offset)` Reads four bytes at `offset` as a big-endian unsigned 32-bit integer. ### `readUint32LE(buf, offset)` Reads four bytes at `offset` as a little-endian unsigned 32-bit integer. ### `readInt32BE(buf, offset)` Reads four bytes at `offset` as a big-endian signed 32-bit integer. Converts unsigned values ≥ 0x80000000 to their negative two's-complement equivalents. ### `readString(buf, offset, length, encoding?)` Decodes `length` bytes starting at `offset`. - `encoding = "utf8"` (default): uses `TextDecoder("utf-8")` for correct multi-byte handling. - `encoding = "latin1"`: maps each byte to its Unicode code point — necessary for ID3v1 and some legacy ID3v2 fields. ### `readSyncsafeInt(buf, offset)` Reads four bytes at `offset` and decodes them as an ID3v2 syncsafe integer (28-bit value, MSB of each byte ignored). Returns a plain `number`. ### `concatBuffers(a, b)` Returns a new `Uint8Array` containing all bytes of `a` followed by all bytes of `b`. ## Implementation Notes The `>>> 0` cast after bit-shifting operations ensures the result is treated as an unsigned 32-bit integer in JavaScript, preventing sign-extension surprises with values whose MSB is set. The `readUint32BE` implementation uses multiplication by `0x1000000` instead of `<< 24` to avoid the signed-integer trap that `<< 24` introduces for bytes with the high bit set. Out-of-bounds array reads return `undefined` in JavaScript, which is coerced to `0` via the `?? 0` fallback — this trades silent safety for parser robustness with truncated buffers.