1[](https://github.com/enarx/ciborium/actions?query=workflow%3A%22test%22) 2[](https://isitmaintained.com/project/enarx/ciborium "Average time to resolve an issue") 3[](https://isitmaintained.com/project/enarx/ciborium "Percentage of issues still open") 4 5 6# ciborium-ll 7 8Low level CBOR parsing tools 9 10This crate contains low-level types for encoding and decoding items in 11CBOR. This crate is usable in both `no_std` and `no_alloc` environments. 12To understand how this crate works, first we will look at the structure 13of a CBOR item on the wire. 14 15## Anatomy of a CBOR Item 16 17This is a brief anatomy of a CBOR item on the wire. 18 19``` 20+------------+-----------+ 21| | | 22| Major | Minor | 23| (3bits) | (5bits) | 24| | | 25+------------+-----------+ 26^ ^ 27| | 28+-----+ +-----+ 29 | | 30 | | 31 +----------------------------+--------------+ 32 | | | | 33 | Prefix | Affix | Suffix | 34 | (1 byte) | (0-8 bytes) | (0+ bytes) | 35 | | | | 36 +------------+---------------+--------------+ 37 38 | | | 39 +------------+---------------+--------------+ 40 | | 41 v v 42 43 Header Body 44``` 45 46The `ciborium` crate works by providing the `Decoder` and `Encoder` types 47which provide input and output for a CBOR header (see: `Header`). From 48there, you can either handle the body yourself or use the provided utility 49functions. 50 51For more information on the CBOR format, see 52[RFC 7049](https://tools.ietf.org/html/rfc7049). 53 54## Decoding 55 56In order to decode CBOR, you will create a `Decoder` from a reader. The 57decoder instance will allow you to `Decoder::pull()` `Header` instances 58from the input. 59 60Most CBOR items are fully contained in their headers and therefore have no 61body. These items can be evaluated directly from the `Header` instance. 62 63Bytes and text items have a body but do not contain child items. Since 64both bytes and text values may be segmented, parsing them can be a bit 65tricky. Therefore, we provide helper functions to parse these types. See 66`Decoder::bytes()` and `Decoder::text()` for more details. 67 68Array and map items have a body which contains child items. These can be 69parsed by simply doing `Decoder::pull()` to parse the child items. 70 71### Example 72 73```rust 74use ciborium_ll::{Decoder, Header}; 75use ciborium_io::Read as _; 76 77let input = b"\x6dHello, World!"; 78let mut decoder = Decoder::from(&input[..]); 79let mut chunks = 0; 80 81match decoder.pull().unwrap() { 82 Header::Text(len) => { 83 let mut segments = decoder.text(len); 84 while let Some(mut segment) = segments.pull().unwrap() { 85 let mut buffer = [0u8; 7]; 86 while let Some(chunk) = segment.pull(&mut buffer[..]).unwrap() { 87 match chunk { 88 "Hello, " if chunks == 0 => chunks = 1, 89 "World!" if chunks == 1 => chunks = 2, 90 _ => panic!("received unexpected chunk"), 91 } 92 } 93 } 94 } 95 96 _ => panic!("received unexpected value"), 97} 98 99assert_eq!(chunks, 2); 100``` 101 102## Encoding 103 104To encode values to CBOR, create an `Encoder` from a writer. The encoder 105instance provides the `Encoder::push()` method to write a `Header` value 106to the wire. CBOR item bodies can be written directly. 107 108For bytes and text, there are the `Encoder::bytes()` and `Encoder::text()` 109utility functions, respectively, which will properly segment the output 110on the wire for you. 111 112### Example 113 114```rust 115use ciborium_ll::{Encoder, Header}; 116use ciborium_io::Write as _; 117 118let mut buffer = [0u8; 19]; 119let mut encoder = Encoder::from(&mut buffer[..]); 120 121// Write the structure 122encoder.push(Header::Map(Some(1))).unwrap(); 123encoder.push(Header::Positive(7)).unwrap(); 124encoder.text("Hello, World!", 7).unwrap(); 125 126// Validate our output 127encoder.flush().unwrap(); 128assert_eq!(b"\xa1\x07\x7f\x67Hello, \x66World!\xff", &buffer[..]); 129``` 130 131License: Apache-2.0 132