# `buffer` — TPM 2.0 octet-stream reader and writer _(no submodules)_ ## Purpose The `buffer` module provides the lowest layer of `@suaveplan/tpm-struct`: a strictly-bounded, big-endian byte reader (`TpmBufferReader`) and a matching growing-array writer (`TpmBufferWriter`) shaped to the TCG TPM 2.0 Library Part 2 §10.1 octet-stream conventions. Every higher-level parser in the package (the `TPMS_ATTEST` decoder, the `TPMT_PUBLIC` decoder, the name serialiser) builds on these primitives, which is why they receive their own subpath export. Keeping bounds enforcement, big-endian semantics, and the `TPM2B_*` size-prefix protocol in one place means the rest of the package can be written as straight-line code without per-field bounds checks or accidental little-endian reads. ## Features - Big-endian readers for UINT8/16/32/64 (the 64-bit form returns a `bigint` so it never silently truncates). - `TPM2B_*` size-prefix reader and writer (UINT16 length + payload). - Cursor-stable error path: out-of-bounds reads raise `TpmStructError(TPM_STRUCT.TRUNCATED)` carrying `cursor` and `requested` on the cause chain so log adapters can format the failure. - `assertEnd()` rejects trailing bytes — guards against silent length drift between the wire format and consumers. - Constant-time-safe `peek(n)` (no advancing, never throws on clip). - Growing writer with geometric reallocation hint via `initialCapacity`. ## Usage: Basic Example ```ts import { TpmBufferReader } from "@suaveplan/tpm-struct/buffer"; const reader = new TpmBufferReader(new Uint8Array([0x00, 0x04, 0xde, 0xad, 0xbe, 0xef])); const payload = reader.readTpm2b(); // Uint8Array[0xde, 0xad, 0xbe, 0xef] reader.assertEnd(); ``` ## Usage: Advanced Example ```ts import { TpmBufferReader, TpmBufferWriter } from "@suaveplan/tpm-struct/buffer"; // Encode then decode an arbitrary TPMS_CLOCK_INFO substructure. const w = new TpmBufferWriter({ initialCapacity: 17 }); w.writeUint64Be(100n); // clock w.writeUint32Be(5); // resetCount w.writeUint32Be(3); // restartCount w.writeUint8(1); // safe = true const bytes = w.toUint8Array(); const r = new TpmBufferReader(bytes); const clock = r.readUint64Be(); const reset = r.readUint32Be(); const restart = r.readUint32Be(); const safe = r.readUint8() !== 0; r.assertEnd(); ``` ## API Reference - **`new TpmBufferReader(bytes, { cursor? })`** — construct over a `Uint8Array`. Out-of-range `cursor` raises `TPM_STRUCT.TRUNCATED`. - **`readUint8 / readUint16Be / readUint32Be`** — return `number`. - **`readUint64Be()`** — returns `bigint`. - **`readBytes(n)`** — returns a fresh `Uint8Array` copy (never aliases). - **`readTpm2b()`** / **`readTpm2bWithSize()`** — TCG `TPM2B_*` size-prefix. - **`peek(n)` / `remaining()` / `cursor()` / `assertEnd()`** — read-only introspection. - **`new TpmBufferWriter({ initialCapacity? })`** — growing writer. - **`writeUint8 / 16Be / 32Be / 64Be / Bytes / Tpm2b`** — mirror writes. - **`toUint8Array()`** — finalise into a fresh `Uint8Array`. ## Implementation Notes The reader holds a single `DataView` over the supplied `Uint8Array`'s backing buffer and advances a private cursor by the exact bytes consumed. `readTpm2b` rewinds the cursor to the start of the size prefix on a short-read failure so callers can produce diagnostic dumps from the failing position. The writer grows its backing array by powers of two starting at `initialCapacity` (default 256) and reuses the same buffer across writes. Numeric range checks reject out-of-range writes at the boundary — this is cheaper than letting `DataView` truncate silently.