Files
skills/docs/foundation/flow/cbor/src/encoder/encoder.md
2026-05-29 08:20:56 +01:00

4.0 KiB
Raw Blame History

encoder

(no submodules)

- half-float — Encodes a JavaScript `number` as IEEE……
  • half-float — Encodes a JavaScript number as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…

  • half-float — Encodes a JavaScript number as IEEE……

  • half-float — Encodes a JavaScript number as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…

  • half-float — Encodes a JavaScript number as IEEE……

  • half-float — Encodes a JavaScript number as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…

  • half-float — Encodes a JavaScript number as IEEE…

  • half-float — Encodes a JavaScript number as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…

  • half-float — Encodes a JavaScript number as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…

Purpose

The CBOR encoder serialises an arbitrary JavaScript value into RFC 8949 binary form. It supports every CBOR major type (0–7) and applies preferred serialisation rules — shortest-form integers always-on, shortest-exact float width by default. It also exposes a deterministic-encoding mode (RFC 8949 §4.2) for callers that need byte-stable output across runs (e.g. signature generation, content addressing).

Features

  • All seven major types: unsigned, negative, byte string, text string, array, map, tag, and major-7 (simple values + floats).
  • Shortest-form integers per RFC 8949 §4.2.1 — always-on, regardless of mode.
  • Shortest-exact float selection among {float16 (opt-in), float32, float64}.
  • Deterministic mode: sorted map keys (lexicographic over canonical encoded key bytes), no indefinite-length items, no half-float, rejects undefined.
  • BigInt support: ranges within ±u64 use major 0/1; outside that range, tag 2 (positive) or tag 3 (negative) bignum byte-string.
  • Tagged<T> round-trip — encode emits tag-then-inner per §3.4.
  • Map<K,V> and plain object literals both serialise to major 5 maps.
  • Configurable maxDepth (default 64) and maxItems (default 1_000_000) guard against pathological inputs.

Usage: Basic Example

import { encode } from "@suaveplan/cbor/encoder";

const bytes = encode({ a: 1, b: [true, "two"] });

Usage: Advanced Example

import { encode } from "@suaveplan/cbor/encoder";
import { Tagged } from "@suaveplan/cbor/tags";

// Deterministic encoding for signing
const claims = new Map<number, unknown>([
  [1, "issuer"],
  [4, new Tagged(1, 1700000000)], // exp claim with epoch tag
]);
const signedBytes = encode(claims, { deterministic: true });

API Reference

  • encode(value: unknown, options?: EncoderOptions): Uint8Array
  • EncoderOptions:
    • deterministic?: boolean — default false. Enforces RFC 8949 §4.2.
    • preferFloat16?: boolean — default false. Try binary16 when exact. Ignored when deterministic is true.
    • maxDepth?: number — default 64. Throws CBOR.NESTED_TOO_DEEP on overflow.
    • maxItems?: number — default 1_000_000. Throws CBOR.LENGTH_OVERFLOW.

Throws CborError with codes UNEXPECTED_TYPE (functions, symbols), NON_DETERMINISTIC (e.g. undefined under deterministic), NESTED_TOO_DEEP, and LENGTH_OVERFLOW.

Implementation Notes

The encoder accumulates output as an array of Uint8Array chunks and concatenates at the end. This avoids the O(n²) cost of repeatedly grow-and- copying a single buffer. Map-key sorting in deterministic mode encodes each key first (yielding the canonical bytes), then sorts the entry list by lexicographic byte order before emitting headers and bodies. BigInt encoding uses native DataView.setBigUint64 for the in-range case and a hand-rolled big-endian byte builder for tag 2/3 bignums to avoid pulling in any external dependency.