Initial Commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# buffer-utils
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## 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.
|
||||
Reference in New Issue
Block a user