1 //! CBOR and serialization.
2 //!
3 //! # Usage
4 //!
5 //! Serde CBOR supports Rust 1.40 and up. Add this to your `Cargo.toml`:
6 //! ```toml
7 //! [dependencies]
8 //! serde_cbor = "0.10"
9 //! ```
10 //!
11 //! Storing and loading Rust types is easy and requires only
12 //! minimal modifications to the program code.
13 //!
14 //! ```rust
15 //! use serde_derive::{Deserialize, Serialize};
16 //! use std::error::Error;
17 //! use std::fs::File;
18 //!
19 //! // Types annotated with `Serialize` can be stored as CBOR.
20 //! // To be able to load them again add `Deserialize`.
21 //! #[derive(Debug, Serialize, Deserialize)]
22 //! struct Mascot {
23 //!     name: String,
24 //!     species: String,
25 //!     year_of_birth: u32,
26 //! }
27 //!
28 //! fn main() -> Result<(), Box<dyn Error>> {
29 //!     let ferris = Mascot {
30 //!         name: "Ferris".to_owned(),
31 //!         species: "crab".to_owned(),
32 //!         year_of_birth: 2015,
33 //!     };
34 //!
35 //!     let ferris_file = File::create("examples/ferris.cbor")?;
36 //!     // Write Ferris to the given file.
37 //!     // Instead of a file you can use any type that implements `io::Write`
38 //!     // like a HTTP body, database connection etc.
39 //!     serde_cbor::to_writer(ferris_file, &ferris)?;
40 //!
41 //!     let tux_file = File::open("examples/tux.cbor")?;
42 //!     // Load Tux from a file.
43 //!     // Serde CBOR performs roundtrip serialization meaning that
44 //!     // the data will not change in any way.
45 //!     let tux: Mascot = serde_cbor::from_reader(tux_file)?;
46 //!
47 //!     println!("{:?}", tux);
48 //!     // prints: Mascot { name: "Tux", species: "penguin", year_of_birth: 1996 }
49 //!
50 //!     Ok(())
51 //! }
52 //! ```
53 //!
54 //! There are a lot of options available to customize the format.
55 //! To operate on untyped CBOR values have a look at the `Value` type.
56 //!
57 //! # Type-based Serialization and Deserialization
58 //! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
59 //! from CBOR via the serialization API. To be able to serialize a piece of data, it must implement
60 //! the `serde::Serialize` trait. To be able to deserialize a piece of data, it must implement the
61 //! `serde::Deserialize` trait. Serde provides an annotation to automatically generate the
62 //! code for these traits: `#[derive(Serialize, Deserialize)]`.
63 //!
64 //! The CBOR API also provides an enum `serde_cbor::Value`.
65 //!
66 //! # Packed Encoding
67 //! When serializing structs or enums in CBOR the keys or enum variant names will be serialized
68 //! as string keys to a map. Especially in embedded environments this can increase the file
69 //! size too much. In packed encoding all struct keys, as well as any enum variant that has no data,
70 //! will be serialized as variable sized integers. The first 24 entries in any struct consume only a
71 //! single byte!  Packed encoding uses serde's preferred [externally tagged enum
72 //! format](https://serde.rs/enum-representations.html) and therefore serializes enum variant names
73 //! as string keys when that variant contains data.  So, in the packed encoding example, `FirstVariant`
74 //! encodes to a single byte, but encoding `SecondVariant` requires 16 bytes.
75 //!
76 //! To serialize a document in this format use `Serializer::new(writer).packed_format()` or
77 //! the shorthand `ser::to_vec_packed`. The deserialization works without any changes.
78 //!
79 //! If you would like to omit the enum variant encoding for all variants, including ones that
80 //! contain data, you can add `legacy_enums()` in addition to `packed_format()`, as can seen
81 //! in the Serialize using minimal encoding example.
82 //!
83 //! # Self describing documents
84 //! In some contexts different formats are used but there is no way to declare the format used
85 //! out of band. For this reason CBOR has a magic number that may be added before any document.
86 //! Self describing documents are created with `serializer.self_describe()`.
87 //!
88 //! # Examples
89 //! Read a CBOR value that is known to be a map of string keys to string values and print it.
90 //!
91 //! ```rust
92 //! use std::collections::BTreeMap;
93 //! use serde_cbor::from_slice;
94 //!
95 //! let slice = b"\xa5aaaAabaBacaCadaDaeaE";
96 //! let value: BTreeMap<String, String> = from_slice(slice).unwrap();
97 //! println!("{:?}", value); // {"e": "E", "d": "D", "a": "A", "c": "C", "b": "B"}
98 //! ```
99 //!
100 //! Read a general CBOR value with an unknown content.
101 //!
102 //! ```rust
103 //! use serde_cbor::from_slice;
104 //! use serde_cbor::value::Value;
105 //!
106 //! let slice = b"\x82\x01\xa1aaab";
107 //! let value: Value = from_slice(slice).unwrap();
108 //! println!("{:?}", value); // Array([U64(1), Object({String("a"): String("b")})])
109 //! ```
110 //!
111 //! Serialize an object.
112 //!
113 //! ```rust
114 //! use std::collections::BTreeMap;
115 //! use serde_cbor::to_vec;
116 //!
117 //! let mut programming_languages = BTreeMap::new();
118 //! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]);
119 //! programming_languages.insert("python", vec!["powerful", "friendly", "open"]);
120 //! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]);
121 //! let encoded = to_vec(&programming_languages);
122 //! assert_eq!(encoded.unwrap().len(), 103);
123 //! ```
124 //!
125 //! Deserializing data in the middle of a slice
126 //! ```
127 //! # extern crate serde_cbor;
128 //! use serde_cbor::Deserializer;
129 //!
130 //! # fn main() {
131 //! let data: Vec<u8> = vec![
132 //!     0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62,
133 //!     0x61, 0x72,
134 //! ];
135 //! let mut deserializer = Deserializer::from_slice(&data);
136 //! let value: &str = serde::de::Deserialize::deserialize(&mut deserializer)
137 //!     .unwrap();
138 //! let rest = &data[deserializer.byte_offset()..];
139 //! assert_eq!(value, "foobar");
140 //! assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
141 //! # }
142 //! ```
143 //!
144 //! Serialize using packed encoding
145 //!
146 //! ```rust
147 //! use serde_derive::{Deserialize, Serialize};
148 //! use serde_cbor::ser::to_vec_packed;
149 //! use WithTwoVariants::*;
150 //!
151 //! #[derive(Debug, Serialize, Deserialize)]
152 //! enum WithTwoVariants {
153 //!     FirstVariant,
154 //!     SecondVariant(u8),
155 //! }
156 //!
157 //! let cbor = to_vec_packed(&FirstVariant).unwrap();
158 //! assert_eq!(cbor.len(), 1);
159 //!
160 //! let cbor = to_vec_packed(&SecondVariant(0)).unwrap();
161 //! assert_eq!(cbor.len(), 16); // Includes 13 bytes of "SecondVariant"
162 //! ```
163 //!
164 //! Serialize using minimal encoding
165 //!
166 //! ```rust
167 //! use serde_derive::{Deserialize, Serialize};
168 //! use serde_cbor::{Result, Serializer, ser::{self, IoWrite}};
169 //! use WithTwoVariants::*;
170 //!
171 //! fn to_vec_minimal<T>(value: &T) -> Result<Vec<u8>>
172 //! where
173 //!     T: serde::Serialize,
174 //! {
175 //!     let mut vec = Vec::new();
176 //!     value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).packed_format().legacy_enums())?;
177 //!     Ok(vec)
178 //! }
179 //!
180 //! #[derive(Debug, Serialize, Deserialize)]
181 //! enum WithTwoVariants {
182 //!     FirstVariant,
183 //!     SecondVariant(u8),
184 //! }
185 //!
186 //! let cbor = to_vec_minimal(&FirstVariant).unwrap();
187 //! assert_eq!(cbor.len(), 1);
188 //!
189 //! let cbor = to_vec_minimal(&SecondVariant(0)).unwrap();
190 //! assert_eq!(cbor.len(), 3);
191 //! ```
192 //!
193 //! # `no-std` support
194 //!
195 //! Serde CBOR supports building in a `no_std` context, use the following lines
196 //! in your `Cargo.toml` dependencies:
197 //! ``` toml
198 //! [dependencies]
199 //! serde = { version = "1.0", default-features = false }
200 //! serde_cbor = { version = "0.10", default-features = false }
201 //! ```
202 //!
203 //! Without the `std` feature the functions [from_reader], [from_slice], [to_vec], and [to_writer]
204 //! are not exported. To export [from_slice] and [to_vec] enable the `alloc` feature. The `alloc`
205 //! feature uses the [`alloc` library][alloc-lib] and requires at least version 1.36.0 of Rust.
206 //!
207 //! [alloc-lib]: https://doc.rust-lang.org/alloc/
208 //!
209 //! *Note*: to use derive macros in serde you will need to declare `serde`
210 //! dependency like so:
211 //! ``` toml
212 //! serde = { version = "1.0", default-features = false, features = ["derive"] }
213 //! ```
214 //!
215 //! Serialize an object with `no_std` and without `alloc`.
216 //! ``` rust
217 //! # #[macro_use] extern crate serde_derive;
218 //! # fn main() -> Result<(), serde_cbor::Error> {
219 //! use serde::Serialize;
220 //! use serde_cbor::Serializer;
221 //! use serde_cbor::ser::SliceWrite;
222 //!
223 //! #[derive(Serialize)]
224 //! struct User {
225 //!     user_id: u32,
226 //!     password_hash: [u8; 4],
227 //! }
228 //!
229 //! let mut buf = [0u8; 100];
230 //! let writer = SliceWrite::new(&mut buf[..]);
231 //! let mut ser = Serializer::new(writer);
232 //! let user = User {
233 //!     user_id: 42,
234 //!     password_hash: [1, 2, 3, 4],
235 //! };
236 //! user.serialize(&mut ser)?;
237 //! let writer = ser.into_inner();
238 //! let size = writer.bytes_written();
239 //! let expected = [
240 //!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
241 //!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
242 //!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
243 //! ];
244 //! assert_eq!(&buf[..size], expected);
245 //! # Ok(())
246 //! # }
247 //! ```
248 //!
249 //! Deserialize an object.
250 //! ``` rust
251 //! # #[macro_use] extern crate serde_derive;
252 //! # fn main() -> Result<(), serde_cbor::Error> {
253 //! #[derive(Debug, PartialEq, Deserialize)]
254 //! struct User {
255 //!     user_id: u32,
256 //!     password_hash: [u8; 4],
257 //! }
258 //!
259 //! let value = [
260 //!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
261 //!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
262 //!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
263 //! ];
264 //!
265 //! // from_slice_with_scratch will not alter input data, use it whenever you
266 //! // borrow from somewhere else.
267 //! // You will have to size your scratch according to the input data you
268 //! // expect.
269 //! use serde_cbor::de::from_slice_with_scratch;
270 //! let mut scratch = [0u8; 32];
271 //! let user: User = from_slice_with_scratch(&value[..], &mut scratch)?;
272 //! assert_eq!(user, User {
273 //!     user_id: 42,
274 //!     password_hash: [1, 2, 3, 4],
275 //! });
276 //!
277 //! let mut value = [
278 //!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
279 //!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
280 //!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
281 //! ];
282 //!
283 //! // from_mut_slice will move data around the input slice, you may only use it
284 //! // on data you may own or can modify.
285 //! use serde_cbor::de::from_mut_slice;
286 //! let user: User = from_mut_slice(&mut value[..])?;
287 //! assert_eq!(user, User {
288 //!     user_id: 42,
289 //!     password_hash: [1, 2, 3, 4],
290 //! });
291 //! # Ok(())
292 //! # }
293 //! ```
294 //!
295 //! # Limitations
296 //!
297 //! While Serde CBOR strives to support all features of Serde and CBOR
298 //! there are a few limitations.
299 //!
300 //! * [Tags] are ignored during deserialization and can't be emitted during
301 //!     serialization. This is because Serde has no concept of tagged
302 //!     values. See:&nbsp;[#3]
303 //! * Unknown [simple values] cause an `UnassignedCode` error.
304 //!     The simple values *False* and *True* are recognized and parsed as bool.
305 //!     *Null* and *Undefined* are both deserialized as *unit*.
306 //!     The *unit* type is serialized as *Null*. See:&nbsp;[#86]
307 //! * [128-bit integers] can't be directly encoded in CBOR. If you need them
308 //!     store them as a byte string. See:&nbsp;[#77]
309 //!
310 //! [Tags]: https://tools.ietf.org/html/rfc7049#section-2.4.4
311 //! [#3]: https://github.com/pyfisch/cbor/issues/3
312 //! [simple values]: https://tools.ietf.org/html/rfc7049#section-3.5
313 //! [#86]: https://github.com/pyfisch/cbor/issues/86
314 //! [128-bit integers]: https://doc.rust-lang.org/std/primitive.u128.html
315 //! [#77]: https://github.com/pyfisch/cbor/issues/77
316 
317 #![deny(missing_docs)]
318 #![cfg_attr(not(feature = "std"), no_std)]
319 
320 // When we are running tests in no_std mode we need to explicitly link std, because `cargo test`
321 // will not work without it.
322 #[cfg(all(not(feature = "std"), test))]
323 extern crate std;
324 
325 #[cfg(feature = "alloc")]
326 extern crate alloc;
327 
328 pub mod de;
329 pub mod error;
330 mod read;
331 pub mod ser;
332 pub mod tags;
333 mod write;
334 
335 #[cfg(feature = "std")]
336 pub mod value;
337 
338 // Re-export the [items recommended by serde](https://serde.rs/conventions.html).
339 #[doc(inline)]
340 pub use crate::de::{Deserializer, StreamDeserializer};
341 
342 #[doc(inline)]
343 pub use crate::error::{Error, Result};
344 
345 #[doc(inline)]
346 pub use crate::ser::Serializer;
347 
348 // Convenience functions for serialization and deserialization.
349 // These functions are only available in `std` mode.
350 #[cfg(feature = "std")]
351 #[doc(inline)]
352 pub use crate::de::from_reader;
353 
354 #[cfg(any(feature = "std", feature = "alloc"))]
355 #[doc(inline)]
356 pub use crate::de::from_slice;
357 
358 #[cfg(any(feature = "std", feature = "alloc"))]
359 #[doc(inline)]
360 pub use crate::ser::to_vec;
361 
362 #[cfg(feature = "std")]
363 #[doc(inline)]
364 pub use crate::ser::to_writer;
365 
366 // Re-export the value type like serde_json
367 #[cfg(feature = "std")]
368 #[doc(inline)]
369 pub use crate::value::Value;
370