1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
|