# `validate` ## Purpose Walk a decoded CBOR value against a parsed CDDL schema and report the first mismatch (with a JSON-pointer-like path). The validator is the run-time counterpart to the parser — given a typed AST and a value, return `{ valid, errors }` describing whether the value conforms. ## Features - All primitive prelude types: `uint`, `nint`, `int`, `bstr`, `tstr`, `bool`, `nil`, `null`, `undefined`, `any`, `number`, `text`, `bytes`, `float` / `float16` / `float32` / `float64`, `tdate` (RFC 3339 string), `time` (number or bigint epoch). - Literal-value matching: text, byte, integer (signed and unsigned), bool, null, undefined. - Range types: inclusive (`..`) and exclusive (`...`). - Choice: tries each alternative in isolation; first match wins. - Arrays: positional `exact`-occurrence entries, optional, one-or-more, zero-or-more, and `M*N` ranges. Extra entries past the schema are rejected. - Maps: text and integer keys; required (`exact`) and optional (`?`) keys; reports the missing key in error messages. - Tagged items via `#6.(T)` parse syntax → typed `{ kind: "tagged" }` AST. - Named references: walks `name = T` rules transparently; entry rule is selectable via `options.rule`. - Control operators: `.size ` (string or bytes length), `.regexp "pattern"` (RegExp match on text), `.cbor T` (left side is bytes). Unknown control operators pass through (treated as informational rather than fail-closed). ## Usage: Basic Example ```ts import { validateCbor } from "@suaveplan/cbor/cddl"; const r = validateCbor({ iss: "alice", exp: 1700000000 }, ` cwt = { iss: tstr, ? exp: int } `); console.log(r.valid); // true ``` ## Usage: Advanced Example ```ts import { parseCddl, validateCbor } from "@suaveplan/cbor/cddl"; const schema = parseCddl(` message = #6.18(cose-sign1) cose-sign1 = [ bstr, { * any => any }, bstr / nil, bstr ] `); import { decode } from "@suaveplan/cbor"; import { Tagged } from "@suaveplan/cbor/tags"; const value = decode(wireBytes, { tagHandling: "raw" }); const r = validateCbor(value, schema, { rule: "message" }); if (!r.valid) { for (const err of r.errors) { console.error(`at ${err.path.join(".")}: expected ${err.expected}, got ${err.got}`); } } ``` ## API Reference - `validateCbor(value: unknown, schema: CddlAst | string, options?: { rule?: string }): CddlValidationResult` - `interface CddlValidationResult { valid: boolean; errors: CddlValidationError[] }` - `interface CddlValidationError { path: (string | number)[]; expected: string; got: string }` Throws `CborError(CDDL_RULE_NOT_FOUND)` if `options.rule` names a rule that doesn't exist; throws `CborError(CDDL_UNDEFINED_REFERENCE)` if a rule body references an undefined name. ## Implementation Notes The walk is a recursive AST switch dispatching on `type.kind`. Choice validation runs each alternative against a fresh sub-context — the first alternative whose walk produces zero errors wins. Map validation accepts both `Map` instances and plain objects; the latter is wrapped via `Object.entries` for uniform key lookup. Array entries are matched greedily within their occurrence-range bound — no backtracking — which is correct for the schemas this package targets but a future extension could add limited backtracking for more permissive schemas.