Skip to content
Carsten Bormann edited this page Nov 22, 2025 · 10 revisions

This wiki page collects useful CDDL snippets that could turn into CDDL idioms.

one-or-more

   one-or-more<T> = T / [ 2* T ]

This describes a type that can be a single T or two or more T items in an array. Note that this only works really well if T cannot be an array; while it may be possible to distinguish the cases if T cannot be an array of T-like items, this requires additional implementation effort.

From RFC9393; import as:

;# import one-or-more from rfc9393

non-empty

   non-empty<M> = (M) .and ({ + any => any })

This describes a map that has at least one entry. It can be used with M being a CDDL rule name, or directly in a map definition:

   problem-details = non-empty<{
     ? &(title: -1) => oltext
     ? &(detail: -2) => oltext
   }>

(Note that this example from RFC 9290 also uses the named-number idiom, below.)

From RFC9115; import as:

;# import non-empty from rfc9115

named numbers

Many CDDL specifications use numbered labels, as in:

   concise-swid-tag = {
     tag-id => text / bstr .size 16,
     tag-version => integer,
   ...

   tag-id = 0
   software-name = 1

(Example extracted from draft-ietf-sacm-coswid-21.txt.)

A shorter snippet with similar semantics is:

   concise-swid-tag = {
     &(tag-id: 0) => text / bstr .size 16,
     &(tag-version: 1) => integer,
   ...

Obviously, this does not define a rule tag-id or tag-version that could be used in other places in the specification, but it associates the number 0 with the label tag-id in a way that tools can access this association.

JC<J, C>

   JC<J,C> = J .feature "json" / C .feature "cbor"

(In this form: From RFC 9165. See below.)

This marks the branches of a choice with feature json and feature cbor. Tools may be able to apply the right subset to a JSON and a CBOR file, for instance to use numeric labels in CBOR and string labels (which are the only ones available) in JSON:

   SenML-Record = {
   ; ...
     ? v => number
   ; ...
   }
   v = JC<"v", 2>

A snippet that may also be useful for a combined JSON and CBOR model:

   base64-string = tstr  ; add regex or ABNF for base64url without padding as needed
   binary-value = JC<base64-string, bstr>

When some parts of the mode are available only for JSON or only for CBOR, the definition of JC can be expanded to include CBOR-ONLY and JSON-ONLY rules:

   JSON-ONLY<J> = J .feature "json"
   CBOR-ONLY<C> = C .feature "cbor"
   JC<J,C> = JSON-ONLY<J> / CBOR-ONLY<C>

From Figure 1 of RFC 9781, UCCS. (Note that versions of the cddl tool before 0.8.29 (May 2022) did not process this correctly; please upgrade to get the bug fix.) Import as:

;# import JC from rfc9781

number ranges

Not all applications need the full numeric ranges that CBOR offers for integer numbers and for floating point values. The following definitions can be copied to application protocol definitions in order to align with the ranges of commonly used platform types:

; C language unsigned integer platform types

uint8  = 0 .. 0xFF
uint16 = 0 .. 0xFFFF
uint32 = 0 .. 0xFFFFFFFF
uint64 = 0 .. 0xFFFFFFFFFFFFFFFF ; same as uint

; C language signed integer platform types
; note that the two's complement assumption used here is now standard C

int8  = -0x80 .. 0x7F
int16 = -0x8000 .. 0x7FFF
int32 = -0x80000000 .. 0x7FFFFFFF
int64 = -0x8000000000000000 .. 0x7FFFFFFFFFFFFFFF

; JavaScript contiguous integer subset of numeric platform type:
; note that this is sign/magitude (smint), not two's complement,
; so, unlike C, the numbers are symmetric around zero

smint53 = -0x1FFFFFFFFFFFFF .. 0x1FFFFFFFFFFFFF

; Floating point (binary64 and binary32/16): exclude non-finites

float-finite = float64-finite
float64-finite = f64-lowest .. f64-max
float32-finite = float32 .and float-finite
float16-finite = float16 .and float-finite

; Floating point ranges/precision of finites

f64-lowest = -0x1.fffffffffffffp+1023; approx. -1.7976931348623157e+308
f64-min = 0x1.0p-1074 ; approx. 5e-324
f64-max = 0x1.fffffffffffffp1023; approx. 1.7976931348623157e+308

f32-lowest = -0x1.fffffep127 ; approx. -3.4028234663852886e+38
f32-min = 0x1.0p-149 ; approx. 1.401298464324817e-45
f32-max = 0x1.fffffep127 ; approx. 3.4028234663852886e+38

f16-lowest = -0x1.ffcp15 ; -65504.0
f16-min = 0x1.0p-24 ; approx. 5.960464477539063e-08
f16-max = 0x1.ffcp15 ; 65504.0

Clone this wiki locally