commit | 98b95916231aba1daae3e86a3aef9422863e64b9 | [log] [tgz] |
---|---|---|
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | Thu Apr 28 15:59:54 2022 +0000 |
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | Thu Apr 28 15:59:54 2022 +0000 |
tree | 56d8252eb446a9eeafd3be964bcba4265e8ecccc | |
parent | 35de108b146bfcb93d18d1a6fa1f7f498d6a75d9 [diff] | |
parent | 39e6bd9c81917079846b648f3b543d269828e2b6 [diff] |
Snap for 8512216 from 39e6bd9c81917079846b648f3b543d269828e2b6 to tm-frc-art-release Change-Id: Iea053c53c05fa25770317b5c23b6a5484ae565a9
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.
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.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