Reader
Read primitive values, control the cursor, and inspect decoding failures.
BsdReader
BsdReader owns the input buffer and mutable decoding state. BSD constructs one
for every schema.decode(input) call. Direct access is primarily useful inside
custom(), modifiers, and .pipe()
callbacks.
State
The reader state is mutable. Every schema decoder is responsible for advancing the internal cursor position and appending/popping path entries. This mutability in on purpose, and ensures we do not create new objects unnecessarily.
| Member | Contract |
|---|---|
buffer |
Source Uint8Array; never copied |
view |
DataView scoped to the source range |
byteOffset |
Current absolute cursor |
schemaOffset |
Starting offset of the active schema |
remaining |
limit - byteOffset |
limit |
Exclusive active-frame boundary |
path |
Active struct keys and array indexes |
Primitive reads
The reader exposes a few methods for reading bytes from its input buffer,
based on the internal cursor position. This improves ergonomics when writing
custom decoders (see custom()) and modifiers.
The reader internals are exposed on purpose, in case you need a scape hatch to implement a schema that is too complex to be expressed through the standard API.
All methods accept the argument advance, which controls whether the internal
cursor advances after reading the value.
| Method | Result | Advances cursor by |
|---|---|---|
uint(bits, advance?) |
number |
1–4 bytes |
int(bits, advance?) |
number |
1–4 bytes |
biguint(bits, advance?) |
bigint |
8 bytes |
bigint(bits, advance?) |
bigint |
8 bytes |
float(bits, advance?) |
number |
4 or 8 bytes |
bool(advance?) |
boolean |
1 byte |
bytes(byteLength, advance?) |
Uint8Array |
byteLength |
const TaggedValue = custom((reader) => {
const tag = reader.uint(8, false);
return tag === 1
? { tag: reader.uint(8), value: reader.uint(16) }
: { tag: reader.uint(8), value: reader.uint(32) };
});
BsdIssue
BSD validation and contextual decoding failures throw BsdIssue, an Error
subclass containing binary context.
| Member | Contract |
|---|---|
message |
Failure description |
schemaOffset |
Starting offset of the failing schema |
byteOffset |
Cursor position when the issue was created |
path |
Struct keys and array indexes leading to the schema |
import { array, BsdIssue, u8 } from "@marceloclp/bsd";
try {
array(3, u8().lte(10)).decode(Uint8Array.of(1, 99, 3));
} catch (error) {
if (error instanceof BsdIssue) {
console.log(error.message); // expected 99 to be less than or equal to 10
console.log(error.schemaOffset); // 1
console.log(error.byteOffset); // 2
console.log(error.path); // [1]
}
}
Use reader.fail(message) to construct a contextual issue in custom logic. It
returns the error; throw it explicitly.
const Version = u8().check((value, reader) => {
if (value !== 2) throw reader.fail(`unsupported version: ${value}`);
});