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 the keys and variants will be serialized as variable sized
70 //! integers. The first 24 entries in any struct consume only a single byte!
71 //! To serialize a document in this format use `Serializer::new(writer).packed_format()` or
72 //! the shorthand `ser::to_vec_packed`. The deserialization works without any changes.
73 //!
74 //! # Self describing documents
75 //! In some contexts different formats are used but there is no way to declare the format used
76 //! out of band. For this reason CBOR has a magic number that may be added before any document.
77 //! Self describing documents are created with `serializer.self_describe()`.
78 //!
79 //! # Examples
80 //! Read a CBOR value that is known to be a map of string keys to string values and print it.
81 //!
82 //! ```rust
83 //! use std::collections::BTreeMap;
84 //! use serde_cbor::from_slice;
85 //!
86 //! let slice = b"\xa5aaaAabaBacaCadaDaeaE";
87 //! let value: BTreeMap<String, String> = from_slice(slice).unwrap();
88 //! println!("{:?}", value); // {"e": "E", "d": "D", "a": "A", "c": "C", "b": "B"}
89 //! ```
90 //!
91 //! Read a general CBOR value with an unknown content.
92 //!
93 //! ```rust
94 //! use serde_cbor::from_slice;
95 //! use serde_cbor::value::Value;
96 //!
97 //! let slice = b"\x82\x01\xa1aaab";
98 //! let value: Value = from_slice(slice).unwrap();
99 //! println!("{:?}", value); // Array([U64(1), Object({String("a"): String("b")})])
100 //! ```
101 //!
102 //! Serialize an object.
103 //!
104 //! ```rust
105 //! use std::collections::BTreeMap;
106 //! use serde_cbor::to_vec;
107 //!
108 //! let mut programming_languages = BTreeMap::new();
109 //! programming_languages.insert("rust", vec!["safe", "concurrent", "fast"]);
110 //! programming_languages.insert("python", vec!["powerful", "friendly", "open"]);
111 //! programming_languages.insert("js", vec!["lightweight", "interpreted", "object-oriented"]);
112 //! let encoded = to_vec(&programming_languages);
113 //! assert_eq!(encoded.unwrap().len(), 103);
114 //! ```
115 //!
116 //! Deserializing data in the middle of a slice
117 //! ```
118 //! # extern crate serde_cbor;
119 //! use serde_cbor::Deserializer;
120 //!
121 //! # fn main() {
122 //! let data: Vec<u8> = vec![
123 //!     0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62,
124 //!     0x61, 0x72,
125 //! ];
126 //! let mut deserializer = Deserializer::from_slice(&data);
127 //! let value: &str = serde::de::Deserialize::deserialize(&mut deserializer)
128 //!     .unwrap();
129 //! let rest = &data[deserializer.byte_offset()..];
130 //! assert_eq!(value, "foobar");
131 //! assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]);
132 //! # }
133 //! ```
134 //!
135 //! # `no-std` support
136 //!
137 //! Serde CBOR supports building in a `no_std` context, use the following lines
138 //! in your `Cargo.toml` dependencies:
139 //! ``` toml
140 //! [dependencies]
141 //! serde = { version = "1.0", default-features = false }
142 //! serde_cbor = { version = "0.10", default-features = false }
143 //! ```
144 //!
145 //! Without the `std` feature the functions [from_reader], [from_slice], [to_vec], and [to_writer]
146 //! are not exported. To export [from_slice] and [to_vec] enable the `alloc` feature. The `alloc`
147 //! feature uses the [`alloc` library][alloc-lib] and requires at least version 1.36.0 of Rust.
148 //!
149 //! [alloc-lib]: https://doc.rust-lang.org/alloc/
150 //!
151 //! *Note*: to use derive macros in serde you will need to declare `serde`
152 //! dependency like so:
153 //! ``` toml
154 //! serde = { version = "1.0", default-features = false, features = ["derive"] }
155 //! ```
156 //!
157 //! Serialize an object with `no_std` and without `alloc`.
158 //! ``` rust
159 //! # #[macro_use] extern crate serde_derive;
160 //! # fn main() -> Result<(), serde_cbor::Error> {
161 //! use serde::Serialize;
162 //! use serde_cbor::Serializer;
163 //! use serde_cbor::ser::SliceWrite;
164 //!
165 //! #[derive(Serialize)]
166 //! struct User {
167 //!     user_id: u32,
168 //!     password_hash: [u8; 4],
169 //! }
170 //!
171 //! let mut buf = [0u8; 100];
172 //! let writer = SliceWrite::new(&mut buf[..]);
173 //! let mut ser = Serializer::new(writer);
174 //! let user = User {
175 //!     user_id: 42,
176 //!     password_hash: [1, 2, 3, 4],
177 //! };
178 //! user.serialize(&mut ser)?;
179 //! let writer = ser.into_inner();
180 //! let size = writer.bytes_written();
181 //! let expected = [
182 //!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
183 //!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
184 //!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
185 //! ];
186 //! assert_eq!(&buf[..size], expected);
187 //! # Ok(())
188 //! # }
189 //! ```
190 //!
191 //! Deserialize an object.
192 //! ``` rust
193 //! # #[macro_use] extern crate serde_derive;
194 //! # fn main() -> Result<(), serde_cbor::Error> {
195 //! #[derive(Debug, PartialEq, Deserialize)]
196 //! struct User {
197 //!     user_id: u32,
198 //!     password_hash: [u8; 4],
199 //! }
200 //!
201 //! let value = [
202 //!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
203 //!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
204 //!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
205 //! ];
206 //!
207 //! // from_slice_with_scratch will not alter input data, use it whenever you
208 //! // borrow from somewhere else.
209 //! // You will have to size your scratch according to the input data you
210 //! // expect.
211 //! use serde_cbor::de::from_slice_with_scratch;
212 //! let mut scratch = [0u8; 32];
213 //! let user: User = from_slice_with_scratch(&value[..], &mut scratch)?;
214 //! assert_eq!(user, User {
215 //!     user_id: 42,
216 //!     password_hash: [1, 2, 3, 4],
217 //! });
218 //!
219 //! let mut value = [
220 //!     0xa2, 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x2a, 0x6d,
221 //!     0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73,
222 //!     0x68, 0x84, 0x1, 0x2, 0x3, 0x4
223 //! ];
224 //!
225 //! // from_mut_slice will move data around the input slice, you may only use it
226 //! // on data you may own or can modify.
227 //! use serde_cbor::de::from_mut_slice;
228 //! let user: User = from_mut_slice(&mut value[..])?;
229 //! assert_eq!(user, User {
230 //!     user_id: 42,
231 //!     password_hash: [1, 2, 3, 4],
232 //! });
233 //! # Ok(())
234 //! # }
235 //! ```
236 //!
237 //! # Limitations
238 //!
239 //! While Serde CBOR strives to support all features of Serde and CBOR
240 //! there are a few limitations.
241 //!
242 //! * [Tags] are ignored during deserialization and can't be emitted during
243 //!     serialization. This is because Serde has no concept of tagged
244 //!     values. See:&nbsp;[#3]
245 //! * Unknown [simple values] cause an `UnassignedCode` error.
246 //!     The simple values *False* and *True* are recognized and parsed as bool.
247 //!     *Null* and *Undefined* are both deserialized as *unit*.
248 //!     The *unit* type is serialized as *Null*. See:&nbsp;[#86]
249 //! * [128-bit integers] can't be directly encoded in CBOR. If you need them
250 //!     store them as a byte string. See:&nbsp;[#77]
251 //!
252 //! [Tags]: https://tools.ietf.org/html/rfc7049#section-2.4.4
253 //! [#3]: https://github.com/pyfisch/cbor/issues/3
254 //! [simple values]: https://tools.ietf.org/html/rfc7049#section-3.5
255 //! [#86]: https://github.com/pyfisch/cbor/issues/86
256 //! [128-bit integers]: https://doc.rust-lang.org/std/primitive.u128.html
257 //! [#77]: https://github.com/pyfisch/cbor/issues/77
258 
259 #![deny(missing_docs)]
260 #![cfg_attr(not(feature = "std"), no_std)]
261 
262 // When we are running tests in no_std mode we need to explicitly link std, because `cargo test`
263 // will not work without it.
264 #[cfg(all(not(feature = "std"), test))]
265 extern crate std;
266 
267 #[cfg(feature = "alloc")]
268 extern crate alloc;
269 
270 pub mod de;
271 pub mod error;
272 mod read;
273 pub mod ser;
274 pub mod tags;
275 mod write;
276 
277 #[cfg(feature = "std")]
278 pub mod value;
279 
280 // Re-export the [items recommended by serde](https://serde.rs/conventions.html).
281 #[doc(inline)]
282 pub use crate::de::{Deserializer, StreamDeserializer};
283 
284 #[doc(inline)]
285 pub use crate::error::{Error, Result};
286 
287 #[doc(inline)]
288 pub use crate::ser::Serializer;
289 
290 // Convenience functions for serialization and deserialization.
291 // These functions are only available in `std` mode.
292 #[cfg(feature = "std")]
293 #[doc(inline)]
294 pub use crate::de::from_reader;
295 
296 #[cfg(any(feature = "std", feature = "alloc"))]
297 #[doc(inline)]
298 pub use crate::de::from_slice;
299 
300 #[cfg(any(feature = "std", feature = "alloc"))]
301 #[doc(inline)]
302 pub use crate::ser::to_vec;
303 
304 #[cfg(feature = "std")]
305 #[doc(inline)]
306 pub use crate::ser::to_writer;
307 
308 // Re-export the value type like serde_json
309 #[cfg(feature = "std")]
310 #[doc(inline)]
311 pub use crate::value::Value;
312