3.3 KiB
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, andM*Nranges. 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.<n>(T)parse syntax → typed{ kind: "tagged" }AST. - Named references: walks
name = Trules transparently; entry rule is selectable viaoptions.rule. - Control operators:
.size <int|range>(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
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
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 }): CddlValidationResultinterface 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.