SkillAgentSearch skills...

Zcbor

Low footprint C/C++ CBOR library and Python tool providing code generation from CDDL descriptions.

Install / Use

/learn @NordicSemiconductor/Zcbor
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

zcbor

zcbor is a low footprint CBOR library in the C language (C++ compatible), tailored for use in microcontrollers. It comes with a schema-driven script tool that can validate your data, or even generate code. The schema language (CDDL) allows creating very advanced and detailed schemas.

The validation and conversion part of the tool works with YAML and JSON data, in addition to CBOR. It can for example validate a YAML file against a schema and convert it into CBOR.

The code generation part of the tool generates C code based on the given schema. The generated code performs CBOR encoding and decoding using the C library, while also validating the data against all the rules in the schema.

The schema language used by zcbor is CDDL (Concise Data Definition Language) which is a powerful human-readable data description language defined in IETF RFC 8610.

Features

Here are some possible ways zcbor can be used:

  • C code:
    • As a low-footprint CBOR decoding/encoding library similar to TinyCBOR/QCBOR/NanoCBOR. The library can be used independently of the Python script. (More information)
    • To generate C code (using the Python script) for validating and decoding or encoding CBOR, for use in optimized or constrained environments, such as microcontrollers. (More information)
  • Python script and module (More information):
    • Validate a YAML/JSON file and translate it into CBOR e.g. for transmission.
    • Validate a YAML/JSON/CBOR file before processing it with some other tool
    • Decode and validate incoming CBOR data into human-readable YAML/JSON.
    • As part of a python script that processes YAML/JSON/CBOR files.
      • Uses the same internal representation used by the PyYAML/json/cbor2 libraries.
      • Do validation against a CDDL schema.
      • Create a read-only representation via named tuples (with names taken from the CDDL schema).

Getting started

There are samples in the samples directory that demonstrate different ways to use zcbor, both the script tool and the C code.

  1. The hello_world sample is a minimum examples of encoding and decoding using the C library.
  2. The pet sample shows a how to use the C library together with generated code, and how to use the script tool to do code generation and data conversion.

The tests also demonstrate how to use zcbor in different ways. The encoding, decoding, and unit tests run using Zephyr (the samples do not use Zephyr).

Should I use code generation or the library directly?

The benefit of using code generation is greater for decoding than encoding. This is because decoding is generally more complex than encoding, since when decoding you have to gracefully handle all possible payloads. The code generation will provide a number of checks that are tedious to write manually. These checks ensure that the payload is well-formed.

CBOR decoding/encoding library

The CBOR library can be found in include/ and src/ and can be used directly, by including the files in your project. If using zcbor with Zephyr, the library will be available when the CONFIG_ZCBOR config is enabled.

The library is also used by generated code. See the Code generation section for more info about code generation.

The C library is C++ compatible.

The zcbor state object

To do encoding or decoding with the library, instantiate a zcbor_state_t object, which is most easily done using the ZCBOR_STATE_*() macros, look below or in the hello_world sample for example code.

The elem_count member refers to the number of encoded objects in the current list or map. elem_count starts again when entering a nested list or map, and is restored when exiting.

elem_count is one reason for needing "backup" states (the other is to allow rollback of the payload). Backups are needed for decoding if there are any lists, maps, or CBOR-encoded strings (zcbor_bstr_*_decode) in the data. Backups are needed for encoding if there are any lists or maps and you are using canonical encoding (ZCBOR_CANONICAL), or when using the zcbor_bstr_*_encode functions.

n_flags is used when decoding maps where the order is unknown. It allows using the zcbor_unordered_map_search() function to search for elements.

See the header files for more information.

/** Initialize a decoding state (could include an array of backup states).
 *  After calling this, decode_state[0] is ready to be used with the decoding APIs. */
ZCBOR_STATE_D(decode_state, n, payload, payload_len, elem_count, n_flags);

/** Initialize an encoding state (could include an array of backup states).
 *  After calling this, encode_state[0] is ready to be used with the encoding APIs. */
ZCBOR_STATE_E(encode_state, n, payload, payload_len, 0);

Configuration

The C library has a few compile-time configuration options. These configuration options can be enabled by adding them as compile definitions to the build. If using zcbor with Zephyr, use the Kconfig options instead.

Name | Description ------------------------- | ----------- ZCBOR_CANONICAL | Assume canonical encoding (AKA "deterministically encoded CBOR", ch 4.2.1 in RFC8949). When encoding lists and maps, do not use indefinite length encoding. Enabling ZCBOR_CANONICAL increases code size and makes the encoding library more often use state backups. When decoding, if enforce_canonical is true, ensure that the incoming data conforms to canonical encoding, i.e. no indefinite length encoding, and always using minimal length encoding (e.g. not using 16 bits to encode a value < 256). Enabling ZCBOR_CANONICAL changes the default of enforce_canonical from false to true Note: the map ordering constraint in canonical encoding is not checked. ZCBOR_VERBOSE | Print log messages on encoding/decoding errors (zcbor_log()), and also a trace message (zcbor_trace()) for each decoded value, and in each generated function (when using code generation). ZCBOR_ASSERTS | Enable asserts (zcbor_assert()). When they fail, the assert statements instruct the current function to return a ZCBOR_ERR_ASSERTION error. If ZCBOR_VERBOSE is enabled, a message is printed. ZCBOR_STOP_ON_ERROR | Enable the stop_on_error functionality. Note that it also has to be enabled in the state variable (state->constant_state->stop_on_error). This makes all zcbor functions abort their execution if called when an error has already happened. ZCBOR_BIG_ENDIAN | All decoded values are returned as big-endian. The default is little-endian. ZCBOR_MAP_SMART_SEARCH | Applies to decoding of unordered maps. When enabled, a flag is kept for each element in an array, ensuring it is not processed twice. If disabled, a count is kept for map as a whole. Enabling increases code size and memory usage, and requires the state variable to possess the memory necessary for the flags.

Canonical encoding

The C library supports some of the rules for canonical encoding (also called "deterministically encoded CBOR"). To enable these, use the ZCBOR_CANONICAL config for encoding, or the enforce_canonical flag for decoding. Note that enabling ZCBOR_CANONICAL changes the default value of enforce_canonical.

Some rules are not supported because it would introduce significant code size or complexity.

The following canonical encoding rules are enforced for encoding:

  • integers are minimally encoded (always)
  • lists and maps do not use indefinite length encoding (when ZCBOR_CANONCAL is enabled)
  • floats are encoded minimally (when using the function zcbor_float_min_encode or zcbor_float_min_put).

The following canonical encoding rules are enforced for decoding:

  • integers are minimally encoded (when enforce_canonical is enabled)
  • lists and maps do not use indefinite length encoding (when enforce_canonical is enabled)

The following canonical encoding rules are not enforced:

  • floats are encoded minimally (during decoding)
  • map keys are sorted by bytewise value

Python script and module

The zcbor.py script can directly read CBOR, YAML, or JSON data and validate it against a CDDL description. It can also freely convert the data between CBOR/YAML/JSON. It can also output the data to a C file formatted as a byte array.

Invoking zcbor.py from the command line

zcbor.py can be installed via pip, or alternatively invoked directly from its location in this repo.

Following are some generalized examples for validating, and for converting (which also validates) data from the command line. The script infers the data format from the file extension, but the format can also be specified explicitly. See zcbor validate --help and zcbor convert --help for more information.

zcbor validate -c <CDDL description file> -t <which CDDL type to expect> -i <input data file>
zcbor convert -c <CDDL description file> -t <which CDDL type to expect> -i <input data file> -o <output data file>

Or directly from within the repo.

python3 <zcbor base>/zcbor/zcbor.py validate -c <CDDL description file> -t <which CDDL type to expect> -i <input data file>
python3 <zcbor base>/zcbor/zcbor.py convert -c <CDDL description fil
View on GitHub
GitHub Stars157
CategoryDevelopment
Updated6h ago
Forks50

Languages

C

Security Score

95/100

Audited on Mar 27, 2026

No findings