MCPcopy Index your code
hub / github.com/anweiss/cddl

github.com/anweiss/cddl @v0.10.6

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.10.6 ↗ · + Follow
838 symbols 2,270 edges 51 files 186 documented · 22% 2 cross-repo links updated 1d agov0.10.6 · 2026-06-29★ 1251 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

cddl-rs

crates.io docs.rs Build and Test Active Development

A Rust implementation of the Concise data definition language (CDDL). CDDL is an IETF standard that "proposes a notational convention to express CBOR and JSON data structures." As of 2019-06-12, it is published as RFC 8610 (Proposed Standard) at https://tools.ietf.org/html/rfc8610.

This crate supports the following CDDL-related RFCs:

RFC Title Status
RFC 8610 Concise Data Definition Language (CDDL) ✔️ Full parsing and validation
RFC 9165 Additional Control Operators for CDDL ✔️ .cat , .det , .plus , .abnf , .abnfb , .feature
RFC 9682 Updates to CDDL (Empty Data Models, \u{hex} Escapes, Non-Literal Tag Numbers) ✔️ Full grammar and parser support
RFC 9741 Additional Control Operators for Text in CDDL ✔️ .b64u , .b64c , .hex , .hexlc , .hexuc , .b32 , .h32 , .b45 , .base10 , .printf , .json , .join and sloppy variants
draft-bormann-cbor-cddl-csv-08 Using CDDL for CSV ✔️ CSV validation via generic data model mapping
draft-bormann-cbor-cddl-freezer-17 CDDL Feature Freezer ✔️ .pcre (PCRE2), .iregexp (RFC 9485), .bitfield

This crate uses Pest (a PEG parser generator for Rust) to parse CDDL. The grammar is defined in cddl.pest and closely follows the ABNF grammar in Appendix B. of the spec. All CDDL must use UTF-8 for its encoding per the spec.

This crate supports validation of CBOR, JSON, and CSV data structures. The minimum supported Rust version (MSRV) is 1.88.0.

Also bundled into this repository is a basic language server implementation and extension for Visual Studio Code for editing CDDL. The implementation is backed by the compiled WebAssembly target included in this crate.

Goals

  • [x] Parse CDDL documents into an AST
  • [x] Verify conformance of CDDL documents against RFC 8610
  • [x] Validate CBOR data structures
  • [x] Validate JSON documents
  • [x] Validate CSV data
  • [x] Generate Rust types from CDDL
  • [ ] Generate dummy JSON from conformant CDDL
  • [x] As close to zero-copy as possible
  • [x] Compile WebAssembly target for browser and Node.js
  • [x] no_std support (lexing and parsing only)
  • [x] Language server implementation and Visual Studio Code Extension

Non-goals

  • Support CBOR diagnostic notation
  • I-JSON compatibility

Used in

This crate is used in several notable projects:

Project Description
google/cddlconv A command-line utility for converting CDDL to TypeScript and Zod schemas
input-output-hk/catalyst-core Core Catalyst governance engine for Cardano, uses this crate for CBOR validation of CIP-36 voter registration data

Why Rust?

Rust is a systems programming language designed around safety and is ideally-suited for resource-constrained systems. CDDL and CBOR are designed around small code and message sizes and constrained nodes, scenarios for which Rust has also been designed.

CLI

A CLI is available for various platforms. The tool supports parsing of CDDL files for verifying conformance against RFC 8610. It can also be used to validate JSON documents, CBOR binary files, and CSV files against CDDL documents. Detailed information about the JSON, CBOR, and CSV validation implementation can be found in the sections below.

Installation

GitHub Releases

Binaries for Linux, macOS and Windows can be downloaded from GitHub Releases.

Cargo

cargo install cddl

Docker

docker pull ghcr.io/anweiss/cddl-cli:latest

CLI usage

Instructions for using the tool can be viewed by executing the help subcommand:

cddl help

If using Docker:

Replace <version> with an appropriate release tag. Requires use of the --volume argument for mounting CDDL documents into the container when executing the command. JSON or CBOR files can either be included in the volume mount or passed into the command via STDIN.

docker run -it --rm -v $PWD:/cddl -w /cddl ghcr.io/anweiss/cddl-cli:<version> help

You can validate JSON documents, CBOR binary files, and/or CSV files:

cddl validate [OPTIONS] --cddl <CDDL> <--stdin|--json <JSON>...|--cbor <CBOR>...|--csv <CSV>...>

For CSV files, use the --csv-header flag if the first row is a header:

cddl validate --cddl schema.cddl --csv data.csv --csv-header

It also supports validating files from STDIN (if it detects the input as valid UTF-8, it will attempt to validate the input as JSON, otherwise it will treat it as CBOR):

cat reputon.json | cddl validate --cddl reputon.cddl --stdin
cat reputon.cbor | cddl validate --cddl reputon.cddl --stdin

or using Docker:

docker run -i --rm -v $PWD:/data -w /data ghcr.io/anweiss/cddl-cli:0.10.4 validate --cddl reputon.cddl --stdin < reputon.json

Website

You can also find a simple RFC 8610 conformance tool at https://cddl.anweiss.tech. This same codebase has been compiled for use in the browser via WebAssembly.

Visual Studio Code extension

An extension for editing CDDL documents with Visual Studio Code has been published to the Marketplace here. You can find more information in the README.

Supported features

  • [x] maps
  • [x] structs
  • [x] tables
  • [x] cuts
  • [x] groups
  • [x] arrays
  • [x] values
  • [x] choices
  • [x] ranges
  • [x] enumeration (building a choice from a group)
  • [x] root type
  • [x] occurrence
  • [x] predefined types
  • [x] tags
  • [x] unwrapping
  • [x] controls
  • [x] socket/plug
  • [x] generics
  • [x] operator precedence
  • [x] comments
  • [x] numerical int/uint values
  • [x] numerical hexfloat values
  • [x] numerical values with exponents
  • [x] unprefixed byte strings
  • [x] prefixed byte strings

Usage

Simply add the dependency to Cargo.toml :

[dependencies]
cddl = "0.10.6"

JSON, CBOR, and CSV validation all require std .

Feature flags

A few convenience features have been included to make the AST more concise and for enabling additional functionality. You can build with default-features = false for a no_std build and selectively enable any of the features below.

--feature ast-span

Add the Span type to the AST for keeping track of the position of the lexer and parser. Enabled by default.

--feature ast-comments

Include comment strings in the AST. Enabled by default.

--feature ast-parent

Add the ParentVisitor implementation so that the AST can be traversed using parent pointers. Enabled by default.

--feature json

Enable JSON validation. Enabled by default.

--feature cbor

Enable CBOR validation. Enabled by default.

--feature csv-validate

Enable CSV validation per draft-bormann-cbor-cddl-csv-08. Enabled by default.

--feature additional-controls

Enable validation support for the additional control operators defined in RFC 9165 and RFC 9741. Enabled by default.

--feature freezer

Enable control operators from the CDDL Feature Freezer draft. Enabled by default. Includes:

  • .pcre — PCRE2 regular expressions via fancy-regex (supports lookahead, lookbehind, backreferences). Patterns are anchored on both sides per the spec.
  • .iregexpRFC 9485 interoperable regular expressions. Anchored matching.
  • .bitfield — Structured bitfield validation for unsigned integers. The controller is an array of bit widths; the validator checks that the uint value fits within the total declared bit width.

Parsing CDDL

use cddl::parser::cddl_from_str;

let input = r#"myrule = int"#;
assert!(cddl_from_str(input, true).is_ok())

Generating Rust types from CDDL

The companion crate cddl-derive provides proc macros for generating Rust types from CDDL definitions at compile time.

[dependencies]
cddl-derive = "0.1"
serde = { version = "1", features = ["derive"] }

Attribute macro — single struct

Apply #[cddl(path = "...")] to a stub struct. The macro reads the CDDL file, finds the matching rule (by converting the struct name from PascalCase to kebab-case), and replaces the struct with fully populated fields:

```rust,ignore use cddl_derive::cddl;

// schema.cddl contains: person = { name: tstr, age: uint, ? email: tstr }

[cddl(path = "schema.cddl")]

struct Person;


This expands at compile time to:

```rust
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Person {
    pub name: String,
    pub age: u64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub email: Option<String>,
}

Use the rule attribute to target a specific CDDL rule name when the struct name does not match:

```rust,ignore

[cddl(path = "schema.cddl", rule = "person-record")]

struct MyPerson;


#### Function-like macro — all types

`cddl_typegen!` generates Rust types for every rule in a CDDL file:

```rust,ignore
use cddl_derive::cddl_typegen;

cddl_typegen!("schema.cddl");
// Generates: struct Person { ... }, struct Address { ... }, etc.

Supported CDDL-to-Rust mappings

CDDL construct Rust output
Map types { key: type, ... } struct with named fields
Type choices a / b / c enum with variants
Simple type references foo = tstr type alias
Array types [* T] Vec<T>
Table types { * tstr => T } HashMap<String, T>
Optional fields ? key: type Option<T> with skip_serializing_if
Nullable types T / null Option<T>
Hyphenated names my-field snake_case field + #[serde(rename = "my-field")]
Rust keywords type, match Escaped with trailing _ + serde rename

All standard prelude types (tstr, uint, int, float, bstr, bool, null, any, etc.) are mapped to their idiomatic Rust equivalents. All generated types include Serialize and Deserialize derives for use with Serde.

Validating JSON

use cddl::validate_json_from_str;

let cddl = r#"person = {
  name: tstr,
  age: uint,
  address: tstr,
}"#;

let json = r#"{
  "name": "John",
  "age": 50,
  "address": "1234 Lakeshore Dr"
}"#;

assert!(validate_json_from_str(cddl, json).is_ok())

This crate uses the Serde framework, and more specifically, the serde_json crate, for parsing and validating JSON. Serde was chosen due to its maturity in the ecosystem and its support for serializing and deserializing CBOR via the ciborium crate.

As outlined in Appendix E. of the standard, only the JSON data model subset of CBOR can be used for validation. The limited prelude from the spec has been included below for brevity:

any = #

uint = #0
nint = #1
int = uint / nint

tstr = #3
text = tstr

number = int / float

float16 = #7.25
float32 = #7.26
float64 = #7.27
float16-32 = float16 / float32
float32-64 = float32 / float64
float = float16-32 / float64

false = #7.20
true = #7.21
bool = false / true
nil = #7.22
null = nil

Furthermore, the following data types from the standard prelude can be used for validating JSON strings and numbers:

tdate = #6.0(tstr)
uri = #6.32(tstr)
b64url = #6.33(tstr)
time = #6.1(number)

The first non-group rule defined by a CDDL data structure definition determines the root type, which is subsequently used for validating the top-level JSON data type.

Supported JSON validation features

The following types and features of CDDL are supported by this crate for validating JSON:

CDDL JSON
structs objects
arrays arrays1
text / tstr string
uri string (valid RFC3986 URI)
tdate string (valid RFC3339 date/time)
b64url string (base64url-encoded)
time number (valid UNIX timestamp integer in seconds)
number / int / float number2
bool / true / false boolean

Extension points exported contracts — how you extend this code

Parent (Interface)
Parent trait retrieving the implemented type's parent [4 implementers]
src/ast/parent.rs
Visitor (Interface)
CDDL AST visitor [3 implementers]
src/visitor.rs
Validator (Interface)
Validator trait. Implemented for JSON documents and CBOR binaries [2 implementers]
src/validator/mod.rs
ItemDetail (Interface)
(no doc)
cddl-lsp/server/src/keywords.ts
ExampleSettings (Interface)
(no doc)
cddl-lsp/server/src/server.ts

Core symbols most depended-on inside this repo

add_error
called by 207
src/validator/cbor.rs
add_error
called by 137
src/validator/json.rs
validate_cbor_from_slice
called by 126
www/cddl.js
insert
called by 82
src/ast/parent.rs
node
called by 80
src/ast/parent.rs
cddl_from_str
called by 79
src/parser.rs
is_ident_string_data_type
called by 50
src/validator/mod.rs
cddl_from_pest_str
called by 37
src/pest_bridge.rs

Shape

Function 599
Method 155
Class 53
Enum 26
Interface 5

Languages

Rust90%
TypeScript10%

Modules by API surface

src/pest_bridge.rs93 symbols
cddl-derive/src/codegen.rs79 symbols
src/validator/cbor.rs58 symbols
src/visitor.rs52 symbols
src/ast/parent.rs50 symbols
src/validator/json.rs46 symbols
src/validator/mod.rs45 symbols
src/ast/mod.rs42 symbols
src/validator/control.rs36 symbols
tests/grammar.rs34 symbols
src/parser_tests.rs34 symbols
cddl-lsp/server/src/server.ts32 symbols

Used by 2 indexed graphs manifest dependencies, hub-wide

For agents

$ claude mcp add cddl \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact