# `@suaveplan/license` — codec/bitpack _(no submodules)_ ## Purpose Bit-precise pack/unpack primitives used to serialise the 72-bit license payload into 9 bytes. Plain `DataView` / typed-array slicing can only write whole bytes, so we walk the buffer bit-by-bit. Two thin classes hold the cursor: `SimpleBitPacker` writes MSB-first, `SimpleBitUnpacker` reads MSB-first. Both round-trip identically to upstream's `@suaveplan/license` bitpacker. ## Features - `packUint(value, bits)` — writes an unsigned integer in `[0, 2^bits)` using `bits` bits; raises `LicenseError(LICENSE.PAYLOAD_OUT_OF_RANGE)` when the value exceeds the declared width or is negative. - `unpackUint(bits)` — reads the next `bits`-wide unsigned integer; raises `LicenseError(LICENSE.MALFORMED)` when the read would underflow the buffer. - `getBytes()` / `getBitCount()` / `getBitPosition()` introspection helpers used by the spec-conformance tests. ## Usage: Basic ```ts import { SimpleBitPacker, SimpleBitUnpacker, } from "@suaveplan/license/codec/bitpack/bitpack"; const p = new SimpleBitPacker(); p.packUint(2, 3); // 3-bit version p.packUint(17, 5); // 5-bit signingKeyId const bytes = p.getBytes(); const u = new SimpleBitUnpacker(bytes); const version = u.unpackUint(3); // 2 const keyId = u.unpackUint(5); // 17 ``` ## Usage: Advanced Round-tripping a full 72-bit payload: ```ts import { FIELD_BITS } from "@suaveplan/license/constants/constants"; import { SimpleBitPacker, SimpleBitUnpacker, } from "@suaveplan/license/codec/bitpack/bitpack"; const p = new SimpleBitPacker(); for (const [_field, bits] of Object.entries(FIELD_BITS)) { p.packUint(0, bits); } const bytes = p.getBytes(); // 9 bytes const u = new SimpleBitUnpacker(bytes); for (const [_field, bits] of Object.entries(FIELD_BITS)) { u.unpackUint(bits); // === 0 } ``` ## API Reference ### `class SimpleBitPacker` - `packUint(value: number, bits: number): void` — write an unsigned integer; throws on overflow / negative. - `getBytes(): Uint8Array` — snapshot the packed bytes. - `getBitCount(): number` — total bits written. ### `class SimpleBitUnpacker` - `constructor(buffer: Uint8Array)` — wrap a byte buffer. - `unpackUint(bits: number): number` — read the next integer; throws `MALFORMED` on underflow. - `getBitPosition(): number` — current read cursor. ## Implementation Notes The packer grows its internal `number[]` buffer one byte at a time because the upstream layout is small (9 bytes) and pre-sizing would require knowing the total bit count in advance. The `1 << bits` overflow check is safe for the bit widths used by the license schema (≤19 bits); for wider integers, callers should use a dedicated bigint bitpacker.