| [](https://github.com/enarx/ciborium/actions?query=workflow%3A%22test%22) |
| [](https://isitmaintained.com/project/enarx/ciborium "Average time to resolve an issue") |
| [](https://isitmaintained.com/project/enarx/ciborium "Percentage of issues still open") |
|  |
| |
| # ciborium-ll |
| |
| 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](https://tools.ietf.org/html/rfc7049). |
| |
| ## Decoding |
| |
| 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. |
| |
| ### Example |
| |
| ```rust |
| 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); |
| ``` |
| |
| ## Encoding |
| |
| 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. |
| |
| ### Example |
| |
| ```rust |
| 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.push(Header::Map(Some(1))).unwrap(); |
| encoder.push(Header::Positive(7)).unwrap(); |
| encoder.text("Hello, World!", 7).unwrap(); |
| |
| // Validate our output |
| encoder.flush().unwrap(); |
| assert_eq!(b"\xa1\x07\x7f\x67Hello, \x66World!\xff", &buffer[..]); |
| ``` |
| |
| License: Apache-2.0 |