diff options
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ca6306 --- /dev/null +++ b/README.md @@ -0,0 +1,131 @@ +[![Workflow Status](https://github.com/enarx/ciborium/workflows/test/badge.svg)](https://github.com/enarx/ciborium/actions?query=workflow%3A%22test%22) +[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/enarx/ciborium.svg)](https://isitmaintained.com/project/enarx/ciborium "Average time to resolve an issue") +[![Percentage of issues still open](https://isitmaintained.com/badge/open/enarx/ciborium.svg)](https://isitmaintained.com/project/enarx/ciborium "Percentage of issues still open") +![Maintenance](https://img.shields.io/badge/maintenance-activly--developed-brightgreen.svg) + +# 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 |