first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
# `buffer` — TPM 2.0 octet-stream reader and writer
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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.