cddl-cat
is a library for validating encoded data against a CDDL
document that describes the expected structure of the data.
Note: This library is fairly new, and may still contain significant bugs, ommissions, or unstable interfaces.
CDDL is a text document described by [RFC8610] that describes data structures. CDDL is not tied to any specific serialization or encoding method; it can be used to validate data that is in [CBOR] or JSON format.
The goal of this library is to make CBOR or JSON data easy to validate against a CDDL schema description.
cddl-cat
supports Rust 1.37 and later.
Supports CBOR and JSON encodings, controlled by the serde_cbor
and
serde_json
features.
An "Intermediate Validation Tree" (IVT) is constructed from the CDDL
AST; this removes some of the CDDL syntax detail resulting in a
simplified tree that can be more easily validated.
The IVT is constructed almost entirely of Node
elements, allowing
recursive validation.
Validation is performed by first translating the incoming data into a generic form, so most of the validation code is completely agnostic to the serialization format.
Validation code uses a Context
object to perform all rule lookups.
This will allow stacking CDDL documents or building CDDL libraries that
can be used by other CDDL schemas. In the future the validation process
itself may be customized by changing the Context
configuration.
This example validates JSON-encoded data against a CDDL schema:
```rust
use cddlcat::validatejson_str;
let cddlinput = "person = {name: tstr, age: int}"; let jsonstr = r#"{ "name": "Bob", "age": 43 }"#;
validatejsonstr("person", cddlinput, &jsonstr).unwrap(); ```
If the JSON data doesn't have the expected structure, an error will result: ```rust
use cddlcat::validatejson_str;
let cddlinput = "person = {name: tstr, age: int}"; let jsonstr = r#"{ "name": "Bob", "age": "forty three" }"#;
assert!(validatejsonstr("person", cddlinput, &jsonstr).is_err()); ```
A similar example, verifying CBOR-encoded data against a CDDL schema: ```rust
use cddlcat::validatecbor_bytes; use serde::Serialize;
struct PersonStruct { name: String, age: u32, }
let input = PersonStruct { name: "Bob".to_string(), age: 43, };
let cborbytes = serdecbor::tovec(&input).unwrap(); let cddlinput = "person = {name: tstr, age: int}";
validatecborbytes("person", cddlinput, &cborbytes).unwrap(); ```
Supported prelude types:
- any
, uint
, nint
, int
, bstr
, bytes
, tstr
, text
- float
, float16
, float32
, float64
, float16-32
, float32-64
\
Note: float sizes are not validated.
Unimplemented features:
- Generics
- Non-cut map keys
- Extend type with /=
- Extend group with //=
- Type sockets with $
- Group sockets with $$
- Range operators ..
, ...
- Control operators, e.g. .size
, .bits
, ...
- Group enumeration with &
- Tagged data with #
- Literal integers with 0x
or 0b
- Hexfloat
- Base64 bytestring literals (b64'...'
)
- Prelude types that invoke CBOR tags (e.g. tdate
or biguint
)