Bug: 216207407

Clone this repo:
  1. 1b2ae7f Update Android.bp by running cargo_embargo by James Farrell · 12 days ago main master
  2. dd23ece Upgrade ciborium-ll to 0.2.2 am: 2791929da2 by David Drysdale · 4 months ago
  3. 2791929 Upgrade ciborium-ll to 0.2.2 by David Drysdale · 4 months ago
  4. b865040 Migrate to cargo_embargo. am: 5f2cd90e64 am: 9637d6faa0 am: 1128d240f0 by Andrew Walbran · 6 months ago
  5. 30872c7 Migrate to cargo_embargo. am: 5f2cd90e64 am: 6c8ee000b5 am: 638d10837f by Andrew Walbran · 6 months ago

Workflow Status Average time to resolve an issue Percentage of issues still open Maintenance


Low level CBOR parsing tools

This crate contains low-level types for encoding and decoding items in CBOR. This crate is usable in both no_std and no_alloc environments. To understand how this crate works, first we will look at the structure of a CBOR item on the wire.

Anatomy of a CBOR Item

This is a brief anatomy of a CBOR item on the wire.

|            |           |
|   Major    |   Minor   |
|  (3bits)   |  (5bits)  |
|            |           |
^                        ^
|                        |
+-----+            +-----+
      |            |
      |            |
      |            |               |              |
      |   Prefix   |     Affix     |    Suffix    |
      |  (1 byte)  |  (0-8 bytes)  |  (0+ bytes)  |
      |            |               |              |

      |                            |              |
                   |                       |
                   v                       v

                 Header                   Body

The ciborium crate works by providing the Decoder and Encoder types which provide input and output for a CBOR header (see: Header). From there, you can either handle the body yourself or use the provided utility functions.

For more information on the CBOR format, see RFC 7049.


In order to decode CBOR, you will create a Decoder from a reader. The decoder instance will allow you to Decoder::pull() Header instances from the input.

Most CBOR items are fully contained in their headers and therefore have no body. These items can be evaluated directly from the Header instance.

Bytes and text items have a body but do not contain child items. Since both bytes and text values may be segmented, parsing them can be a bit tricky. Therefore, we provide helper functions to parse these types. See Decoder::bytes() and Decoder::text() for more details.

Array and map items have a body which contains child items. These can be parsed by simply doing Decoder::pull() to parse the child items.


use ciborium_ll::{Decoder, Header};
use ciborium_io::Read as _;

let input = b"\x6dHello, World!";
let mut decoder = Decoder::from(&input[..]);
let mut chunks = 0;

match decoder.pull().unwrap() {
    Header::Text(len) => {
        let mut segments = decoder.text(len);
        while let Some(mut segment) = segments.pull().unwrap() {
            let mut buffer = [0u8; 7];
            while let Some(chunk) = segment.pull(&mut buffer[..]).unwrap() {
                 match chunk {
                     "Hello, " if chunks == 0 => chunks = 1,
                     "World!" if chunks == 1 => chunks = 2,
                     _ => panic!("received unexpected chunk"),

    _ => panic!("received unexpected value"),

assert_eq!(chunks, 2);


To encode values to CBOR, create an Encoder from a writer. The encoder instance provides the Encoder::push() method to write a Header value to the wire. CBOR item bodies can be written directly.

For bytes and text, there are the Encoder::bytes() and Encoder::text() utility functions, respectively, which will properly segment the output on the wire for you.


use ciborium_ll::{Encoder, Header};
use ciborium_io::Write as _;

let mut buffer = [0u8; 19];
let mut encoder = Encoder::from(&mut buffer[..]);

// Write the structure
encoder.text("Hello, World!", 7).unwrap();

// Validate our output
assert_eq!(b"\xa1\x07\x7f\x67Hello, \x66World!\xff", &buffer[..]);

License: Apache-2.0