first commit
This commit is contained in:
66
docs/foundation/flow/cbor/src/sequences/sequences.md
Normal file
66
docs/foundation/flow/cbor/src/sequences/sequences.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# `sequences`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`@suaveplan/cbor/sequences` implements RFC 8742 — the CBOR Sequence format,
|
||||
which is just the concatenation of zero-or-more well-formed CBOR data items
|
||||
with no enclosing array, tag, or framing byte. Sequences are the natural
|
||||
encoding for log streams, event journals, and any wire format where items
|
||||
arrive incrementally and the consumer does not know the count ahead of time.
|
||||
|
||||
## Features
|
||||
|
||||
- `encodeSequence(items, options?)` produces the byte-concatenated form of an
|
||||
arbitrary item list. Empty input → empty output (zero bytes).
|
||||
- `decodeSequence(bytes, options?, tags?)` walks the input from offset 0,
|
||||
pulling one item at a time via `decodeOne` until the buffer is exhausted.
|
||||
- `decodeSequenceStream(stream, options?, tags?)` — async generator over an
|
||||
`AsyncIterable<Uint8Array>`. Yields each complete item as it becomes
|
||||
available; buffers only what is needed for the next pending item.
|
||||
- All three preserve the strict / lax mode and tag-handling semantics of the
|
||||
underlying decoder — sequence framing is a pure outer concern.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { decodeSequence, encodeSequence } from "@suaveplan/cbor/sequences";
|
||||
|
||||
const wire = encodeSequence([{ id: 1, ok: true }, { id: 2, ok: false }]);
|
||||
const items = decodeSequence(wire);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { decodeSequenceStream } from "@suaveplan/cbor/sequences";
|
||||
|
||||
async function consumeLog(stream: AsyncIterable<Uint8Array>) {
|
||||
for await (const event of decodeSequenceStream(stream)) {
|
||||
handle(event);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `encodeSequence(items: readonly unknown[], options?: EncoderOptions): Uint8Array`
|
||||
- `decodeSequence(bytes: Uint8Array, options?: DecoderOptions, tags?: ReadonlyMap<number, TagHandler>): DecodedValue[]`
|
||||
- `decodeSequenceStream(stream: AsyncIterable<Uint8Array>, options?, tags?): AsyncGenerator<DecodedValue>`
|
||||
|
||||
Throws `CborError(MALFORMED)` for sequence-internal incompleteness (e.g.
|
||||
trailing bytes that don't form a complete item at end-of-stream).
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The streaming form coalesces partial chunks via a growing `Uint8Array`
|
||||
buffer. After each new chunk is appended, the loop attempts as many full
|
||||
`decodeOne` calls as the buffer allows; on the first failure (which signals
|
||||
"need more bytes"), the loop breaks and waits for the next chunk. This
|
||||
strategy is correct as long as `decodeOne` either succeeds and reports
|
||||
exactly `consumed` bytes OR throws — both invariants are guaranteed by the
|
||||
strict-mode decoder. The buffer is reallocated rather than `subarray`d after
|
||||
each successful decode so backing-buffer ownership stays bound to the
|
||||
generator and does not leak into yielded values.
|
||||
Reference in New Issue
Block a user