1 // SPDX-License-Identifier: Apache-2.0 2 3 //! Low level CBOR parsing tools 4 //! 5 //! This crate contains low-level types for encoding and decoding items in 6 //! CBOR. This crate is usable in both `no_std` and `no_alloc` environments. 7 //! To understand how this crate works, first we will look at the structure 8 //! of a CBOR item on the wire. 9 //! 10 //! # Anatomy of a CBOR Item 11 //! 12 //! This is a brief anatomy of a CBOR item on the wire. 13 //! 14 //! ```text 15 //! +------------+-----------+ 16 //! | | | 17 //! | Major | Minor | 18 //! | (3bits) | (5bits) | 19 //! | | | 20 //! +------------+-----------+ 21 //! ^ ^ 22 //! | | 23 //! +-----+ +-----+ 24 //! | | 25 //! | | 26 //! +----------------------------+--------------+ 27 //! | | | | 28 //! | Prefix | Affix | Suffix | 29 //! | (1 byte) | (0-8 bytes) | (0+ bytes) | 30 //! | | | | 31 //! +------------+---------------+--------------+ 32 //! 33 //! | | | 34 //! +------------+---------------+--------------+ 35 //! | | 36 //! v v 37 //! 38 //! Header Body 39 //! ``` 40 //! 41 //! The `ciborium` crate works by providing the `Decoder` and `Encoder` types 42 //! which provide input and output for a CBOR header (see: `Header`). From 43 //! there, you can either handle the body yourself or use the provided utility 44 //! functions. 45 //! 46 //! For more information on the CBOR format, see 47 //! [RFC 7049](https://tools.ietf.org/html/rfc7049). 48 //! 49 //! # Decoding 50 //! 51 //! In order to decode CBOR, you will create a `Decoder` from a reader. The 52 //! decoder instance will allow you to `Decoder::pull()` `Header` instances 53 //! from the input. 54 //! 55 //! Most CBOR items are fully contained in their headers and therefore have no 56 //! body. These items can be evaluated directly from the `Header` instance. 57 //! 58 //! Bytes and text items have a body but do not contain child items. Since 59 //! both bytes and text values may be segmented, parsing them can be a bit 60 //! tricky. Therefore, we provide helper functions to parse these types. See 61 //! `Decoder::bytes()` and `Decoder::text()` for more details. 62 //! 63 //! Array and map items have a body which contains child items. These can be 64 //! parsed by simply doing `Decoder::pull()` to parse the child items. 65 //! 66 //! ## Example 67 //! 68 //! ```rust 69 //! use ciborium_ll::{Decoder, Header}; 70 //! use ciborium_io::Read as _; 71 //! 72 //! let input = b"\x6dHello, World!"; 73 //! let mut decoder = Decoder::from(&input[..]); 74 //! let mut chunks = 0; 75 //! 76 //! match decoder.pull().unwrap() { 77 //! Header::Text(len) => { 78 //! let mut segments = decoder.text(len); 79 //! while let Some(mut segment) = segments.pull().unwrap() { 80 //! let mut buffer = [0u8; 7]; 81 //! while let Some(chunk) = segment.pull(&mut buffer[..]).unwrap() { 82 //! match chunk { 83 //! "Hello, " if chunks == 0 => chunks = 1, 84 //! "World!" if chunks == 1 => chunks = 2, 85 //! _ => panic!("received unexpected chunk"), 86 //! } 87 //! } 88 //! } 89 //! } 90 //! 91 //! _ => panic!("received unexpected value"), 92 //! } 93 //! 94 //! assert_eq!(chunks, 2); 95 //! ``` 96 //! 97 //! # Encoding 98 //! 99 //! To encode values to CBOR, create an `Encoder` from a writer. The encoder 100 //! instance provides the `Encoder::push()` method to write a `Header` value 101 //! to the wire. CBOR item bodies can be written directly. 102 //! 103 //! For bytes and text, there are the `Encoder::bytes()` and `Encoder::text()` 104 //! utility functions, respectively, which will properly segment the output 105 //! on the wire for you. 106 //! 107 //! ## Example 108 //! 109 //! ```rust 110 //! use ciborium_ll::{Encoder, Header}; 111 //! use ciborium_io::Write as _; 112 //! 113 //! let mut buffer = [0u8; 19]; 114 //! let mut encoder = Encoder::from(&mut buffer[..]); 115 //! 116 //! // Write the structure 117 //! encoder.push(Header::Map(Some(1))).unwrap(); 118 //! encoder.push(Header::Positive(7)).unwrap(); 119 //! encoder.text("Hello, World!", 7).unwrap(); 120 //! 121 //! // Validate our output 122 //! encoder.flush().unwrap(); 123 //! assert_eq!(b"\xa1\x07\x7f\x67Hello, \x66World!\xff", &buffer[..]); 124 //! ``` 125 126 #![cfg_attr(not(feature = "std"), no_std)] 127 #![deny(missing_docs)] 128 #![deny(clippy::all)] 129 #![deny(clippy::cargo)] 130 131 #[cfg(feature = "alloc")] 132 extern crate alloc; 133 134 mod dec; 135 mod enc; 136 mod hdr; 137 mod seg; 138 139 pub use dec::*; 140 pub use enc::*; 141 pub use hdr::*; 142 pub use seg::{Segment, Segments}; 143 144 /// Simple value constants 145 pub mod simple { 146 #![allow(missing_docs)] 147 148 pub const FALSE: u8 = 20; 149 pub const TRUE: u8 = 21; 150 pub const NULL: u8 = 22; 151 pub const UNDEFINED: u8 = 23; 152 } 153 154 /// Tag constants 155 pub mod tag { 156 #![allow(missing_docs)] 157 158 pub const BIGPOS: u64 = 2; 159 pub const BIGNEG: u64 = 3; 160 } 161 162 #[derive(Debug)] 163 struct InvalidError(()); 164 165 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 166 enum Major { 167 Positive, 168 Negative, 169 Bytes, 170 Text, 171 Array, 172 Map, 173 Tag, 174 Other, 175 } 176 177 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 178 enum Minor { 179 This(u8), 180 Next1([u8; 1]), 181 Next2([u8; 2]), 182 Next4([u8; 4]), 183 Next8([u8; 8]), 184 More, 185 } 186 187 impl AsRef<[u8]> for Minor { 188 #[inline] as_ref(&self) -> &[u8]189 fn as_ref(&self) -> &[u8] { 190 match self { 191 Self::More => &[], 192 Self::This(..) => &[], 193 Self::Next1(x) => x.as_ref(), 194 Self::Next2(x) => x.as_ref(), 195 Self::Next4(x) => x.as_ref(), 196 Self::Next8(x) => x.as_ref(), 197 } 198 } 199 } 200 201 impl AsMut<[u8]> for Minor { 202 #[inline] as_mut(&mut self) -> &mut [u8]203 fn as_mut(&mut self) -> &mut [u8] { 204 match self { 205 Self::More => &mut [], 206 Self::This(..) => &mut [], 207 Self::Next1(x) => x.as_mut(), 208 Self::Next2(x) => x.as_mut(), 209 Self::Next4(x) => x.as_mut(), 210 Self::Next8(x) => x.as_mut(), 211 } 212 } 213 } 214 215 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 216 struct Title(pub Major, pub Minor); 217 218 #[cfg(test)] 219 mod tests { 220 use super::*; 221 222 macro_rules! neg { 223 ($i:expr) => { 224 Header::Negative((($i as i128) ^ !0) as u64) 225 }; 226 } 227 228 #[allow(clippy::excessive_precision)] 229 #[test] leaf()230 fn leaf() { 231 use core::f64::{INFINITY, NAN}; 232 233 let data = &[ 234 (Header::Positive(0), "00", true), 235 (Header::Positive(1), "01", true), 236 (Header::Positive(10), "0a", true), 237 (Header::Positive(23), "17", true), 238 (Header::Positive(24), "1818", true), 239 (Header::Positive(25), "1819", true), 240 (Header::Positive(100), "1864", true), 241 (Header::Positive(1000), "1903e8", true), 242 (Header::Positive(1000000), "1a000f4240", true), 243 (Header::Positive(1000000000000), "1b000000e8d4a51000", true), 244 ( 245 Header::Positive(18446744073709551615), 246 "1bffffffffffffffff", 247 true, 248 ), 249 (neg!(-18446744073709551616), "3bffffffffffffffff", true), 250 (neg!(-1), "20", true), 251 (neg!(-10), "29", true), 252 (neg!(-100), "3863", true), 253 (neg!(-1000), "3903e7", true), 254 (Header::Float(0.0), "f90000", true), 255 (Header::Float(-0.0), "f98000", true), 256 (Header::Float(1.0), "f93c00", true), 257 (Header::Float(1.1), "fb3ff199999999999a", true), 258 (Header::Float(1.5), "f93e00", true), 259 (Header::Float(65504.0), "f97bff", true), 260 (Header::Float(100000.0), "fa47c35000", true), 261 (Header::Float(3.4028234663852886e+38), "fa7f7fffff", true), 262 (Header::Float(1.0e+300), "fb7e37e43c8800759c", true), 263 (Header::Float(5.960464477539063e-8), "f90001", true), 264 (Header::Float(0.00006103515625), "f90400", true), 265 (Header::Float(-4.0), "f9c400", true), 266 (Header::Float(-4.1), "fbc010666666666666", true), 267 (Header::Float(INFINITY), "f97c00", true), 268 (Header::Float(NAN), "f97e00", true), 269 (Header::Float(-INFINITY), "f9fc00", true), 270 (Header::Float(INFINITY), "fa7f800000", false), 271 (Header::Float(NAN), "fa7fc00000", false), 272 (Header::Float(-INFINITY), "faff800000", false), 273 (Header::Float(INFINITY), "fb7ff0000000000000", false), 274 (Header::Float(NAN), "fb7ff8000000000000", false), 275 (Header::Float(-INFINITY), "fbfff0000000000000", false), 276 (Header::Simple(simple::FALSE), "f4", true), 277 (Header::Simple(simple::TRUE), "f5", true), 278 (Header::Simple(simple::NULL), "f6", true), 279 (Header::Simple(simple::UNDEFINED), "f7", true), 280 (Header::Simple(16), "f0", true), 281 (Header::Simple(24), "f818", true), 282 (Header::Simple(255), "f8ff", true), 283 (Header::Tag(0), "c0", true), 284 (Header::Tag(1), "c1", true), 285 (Header::Tag(23), "d7", true), 286 (Header::Tag(24), "d818", true), 287 (Header::Tag(32), "d820", true), 288 (Header::Bytes(Some(0)), "40", true), 289 (Header::Bytes(Some(4)), "44", true), 290 (Header::Text(Some(0)), "60", true), 291 (Header::Text(Some(4)), "64", true), 292 ]; 293 294 for (header, bytes, encode) in data.iter().cloned() { 295 let bytes = hex::decode(bytes).unwrap(); 296 297 let mut decoder = Decoder::from(&bytes[..]); 298 match (header, decoder.pull().unwrap()) { 299 // NaN equality... 300 (Header::Float(l), Header::Float(r)) if l.is_nan() && r.is_nan() => (), 301 302 // Everything else... 303 (l, r) => assert_eq!(l, r), 304 } 305 306 if encode { 307 let mut buffer = [0u8; 1024]; 308 let mut writer = &mut buffer[..]; 309 let mut encoder = Encoder::from(&mut writer); 310 encoder.push(header).unwrap(); 311 312 let len = writer.len(); 313 assert_eq!(&bytes[..], &buffer[..1024 - len]); 314 } 315 } 316 } 317 318 #[test] node()319 fn node() { 320 let data: &[(&str, &[Header])] = &[ 321 ("80", &[Header::Array(Some(0))]), 322 ( 323 "83010203", 324 &[ 325 Header::Array(Some(3)), 326 Header::Positive(1), 327 Header::Positive(2), 328 Header::Positive(3), 329 ], 330 ), 331 ( 332 "98190102030405060708090a0b0c0d0e0f101112131415161718181819", 333 &[ 334 Header::Array(Some(25)), 335 Header::Positive(1), 336 Header::Positive(2), 337 Header::Positive(3), 338 Header::Positive(4), 339 Header::Positive(5), 340 Header::Positive(6), 341 Header::Positive(7), 342 Header::Positive(8), 343 Header::Positive(9), 344 Header::Positive(10), 345 Header::Positive(11), 346 Header::Positive(12), 347 Header::Positive(13), 348 Header::Positive(14), 349 Header::Positive(15), 350 Header::Positive(16), 351 Header::Positive(17), 352 Header::Positive(18), 353 Header::Positive(19), 354 Header::Positive(20), 355 Header::Positive(21), 356 Header::Positive(22), 357 Header::Positive(23), 358 Header::Positive(24), 359 Header::Positive(25), 360 ], 361 ), 362 ("a0", &[Header::Map(Some(0))]), 363 ( 364 "a201020304", 365 &[ 366 Header::Map(Some(2)), 367 Header::Positive(1), 368 Header::Positive(2), 369 Header::Positive(3), 370 Header::Positive(4), 371 ], 372 ), 373 ("9fff", &[Header::Array(None), Header::Break]), 374 ( 375 "9f018202039f0405ffff", 376 &[ 377 Header::Array(None), 378 Header::Positive(1), 379 Header::Array(Some(2)), 380 Header::Positive(2), 381 Header::Positive(3), 382 Header::Array(None), 383 Header::Positive(4), 384 Header::Positive(5), 385 Header::Break, 386 Header::Break, 387 ], 388 ), 389 ( 390 "9f01820203820405ff", 391 &[ 392 Header::Array(None), 393 Header::Positive(1), 394 Header::Array(Some(2)), 395 Header::Positive(2), 396 Header::Positive(3), 397 Header::Array(Some(2)), 398 Header::Positive(4), 399 Header::Positive(5), 400 Header::Break, 401 ], 402 ), 403 ( 404 "83018202039f0405ff", 405 &[ 406 Header::Array(Some(3)), 407 Header::Positive(1), 408 Header::Array(Some(2)), 409 Header::Positive(2), 410 Header::Positive(3), 411 Header::Array(None), 412 Header::Positive(4), 413 Header::Positive(5), 414 Header::Break, 415 ], 416 ), 417 ( 418 "83019f0203ff820405", 419 &[ 420 Header::Array(Some(3)), 421 Header::Positive(1), 422 Header::Array(None), 423 Header::Positive(2), 424 Header::Positive(3), 425 Header::Break, 426 Header::Array(Some(2)), 427 Header::Positive(4), 428 Header::Positive(5), 429 ], 430 ), 431 ( 432 "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff", 433 &[ 434 Header::Array(None), 435 Header::Positive(1), 436 Header::Positive(2), 437 Header::Positive(3), 438 Header::Positive(4), 439 Header::Positive(5), 440 Header::Positive(6), 441 Header::Positive(7), 442 Header::Positive(8), 443 Header::Positive(9), 444 Header::Positive(10), 445 Header::Positive(11), 446 Header::Positive(12), 447 Header::Positive(13), 448 Header::Positive(14), 449 Header::Positive(15), 450 Header::Positive(16), 451 Header::Positive(17), 452 Header::Positive(18), 453 Header::Positive(19), 454 Header::Positive(20), 455 Header::Positive(21), 456 Header::Positive(22), 457 Header::Positive(23), 458 Header::Positive(24), 459 Header::Positive(25), 460 Header::Break, 461 ], 462 ), 463 ]; 464 465 for (bytes, headers) in data { 466 let bytes = hex::decode(bytes).unwrap(); 467 468 // Test decoding 469 let mut decoder = Decoder::from(&bytes[..]); 470 for header in headers.iter().cloned() { 471 assert_eq!(header, decoder.pull().unwrap()); 472 } 473 474 // Test encoding 475 let mut buffer = [0u8; 1024]; 476 let mut writer = &mut buffer[..]; 477 let mut encoder = Encoder::from(&mut writer); 478 479 for header in headers.iter().cloned() { 480 encoder.push(header).unwrap(); 481 } 482 483 let len = writer.len(); 484 assert_eq!(&bytes[..], &buffer[..1024 - len]); 485 } 486 } 487 } 488