Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
# bitset
## Purpose
Implements the wire-format bitset codec for the mesh protocol. Bitsets carry chunk presence (`cd:advertise`) and chunk-need maps (`cd:request` `kind:'bitset'`); their on-wire representation is a deterministic, magic-prefixed, length-tagged envelope so receivers can detect and reject payloads that bypassed the mandated framing layer (DMP-21). This module also provides the raw bit-manipulation helpers (`chunkIdsToRawBitset`, `rawBitsetToChunkIds`, `popcount`) that the rest of the package consumes.
## Features
- `BITSET_MAGIC` (4-byte `"DMPB"` prefix) + `BITSET_HEADER_SIZE` (12-byte fixed header).
- `encodeBitset(rawBytes, bitLength)` — wraps a raw bit-packed buffer with the header.
- `decodeBitset(wire)` — verifies magic, decodes header, returns `{ raw, bitLength }`; throws `DMP.CODEC_MISMATCH` for missing magic / truncated headers / length mismatches.
- `chunkIdsToRawBitset(ids, bitLength)` — packs a chunk-id list into a raw bit-packed buffer with strict bounds checking.
- `rawBitsetToChunkIds(bytes, bitLength)` — inverse, with padding-zero enforcement (DMP-08).
- `popcount(bytes)` — population count (Hamming weight) over a raw byte array; used by trust accounting.
- All length / padding violations raise `DMP.BITSET_LENGTH_MISMATCH` or `DMP.BITSET_PADDING_NONZERO`.
## Usage: Basic Example
```ts
import {
chunkIdsToRawBitset,
decodeBitset,
encodeBitset,
rawBitsetToChunkIds,
} from "@suaveplan/drive-mesh-protocol";
const raw = chunkIdsToRawBitset([0, 5, 17], 18);
const wire = encodeBitset(raw, 18);
const back = decodeBitset(wire);
const ids = rawBitsetToChunkIds(back.raw, back.bitLength); // [0, 5, 17]
```
## Usage: Advanced Example
```ts
import {
BITSET_HEADER_SIZE,
BITSET_MAGIC,
encodeBitset,
popcount,
} from "@suaveplan/drive-mesh-protocol";
function buildPresence(present: number[], totalChunks: number): Uint8Array {
const raw = chunkIdsToRawBitset(present, totalChunks);
const wire = encodeBitset(raw, totalChunks);
console.log(
`${present.length}/${totalChunks} chunks; ${popcount(raw)} set bits;` +
` wire size ${wire.length} (${BITSET_HEADER_SIZE}-byte header)`
);
return wire;
}
```
## API Reference
- `BITSET_MAGIC: Uint8Array` — 4-byte prefix `0x44 0x4d 0x50 0x42`.
- `BITSET_HEADER_SIZE: 12` — magic + bitLength + rawByteLen.
- `encodeBitset(rawBytes: Uint8Array, bitLength: number): Uint8Array`.
- `decodeBitset(wire: Uint8Array): { raw: Uint8Array; bitLength: number }`.
- `chunkIdsToRawBitset(chunkIds: readonly number[], bitLength: number): Uint8Array`.
- `rawBitsetToChunkIds(bytes: Uint8Array, bitLength: number): number[]`.
- `popcount(bytes: Uint8Array): number`.
## Implementation Notes
The wire format does NOT compress the bitset body — the documented `bitpacker-compressed` mandate is satisfied by the magic + length envelope, which is itself a length-prefixed, self-describing frame. The `compressRle` fast path in `@suaveplan/bitpacker-compressed` is non-bijective on inputs containing isolated `[X, 0, …]` triples and is therefore unsuitable for arbitrary bitset bytes; switching to gzip would force the codec async and break the hot path. The trade-off is intentional and documented inline in the source.