musli/descriptive/
mod.rs

1//! A fully self-descriptive format for [Müsli].
2//!
3//! Descriptive encoding is fully upgrade stable:
4//!
5//! * ✔ Can tolerate missing fields if they are annotated with
6//!   `#[musli(default)]`.
7//! * ✔ Can skip over unknown fields.
8//! * ✔ Can be fully converted back and forth between dynamic containers such as
9//!   the [`Value`] type.
10//! * ✔ Can handle coercion from different types of primitive types, such as
11//!   signed to unsigned integers. So primitive field types can be assuming they
12//!   only inhabit compatible values.
13//!
14//! [Müsli]: https://docs.rs/musli
15//! [`Value`]: crate::value
16//!
17//! This means that it's suitable as a wire and general interchange format. It's
18//! also suitable for dynamically translating to and from different wire formats
19//! such as JSON without having access to the data model.
20//!
21//! ```
22//! use musli::{Encode, Decode};
23//!
24//! #[derive(Debug, PartialEq, Encode, Decode)]
25//! struct Version1 {
26//!     name: String,
27//! }
28//!
29//! #[derive(Debug, PartialEq, Encode, Decode)]
30//! struct Version2 {
31//!     name: String,
32//!     #[musli(default)]
33//!     age: Option<u32>,
34//! }
35//!
36//! let version2 = musli::descriptive::to_vec(&Version2 {
37//!     name: String::from("Aristotle"),
38//!     age: Some(61),
39//! })?;
40//!
41//! let version1: Version1 = musli::descriptive::decode(version2.as_slice())?;
42//!
43//! assert_eq!(version1, Version1 {
44//!     name: String::from("Aristotle"),
45//! });
46//! # Ok::<_, musli::descriptive::Error>(())
47//! ```
48//!
49//! <br>
50//!
51//! ## Configuring
52//!
53//! To configure the behavior of the wire format you can use the [`Encoding`]
54//! type:
55//!
56//! ```
57//! use musli::{Encode, Decode};
58//! use musli::descriptive::Encoding;
59//!
60//! const CONFIG: Encoding = Encoding::new();
61//!
62//! #[derive(Debug, PartialEq, Encode, Decode)]
63//! struct Person<'a> {
64//!     name: &'a str,
65//!     age: u32,
66//! }
67//!
68//! let mut out = Vec::new();
69//!
70//! let expected = Person {
71//!     name: "Aristotle",
72//!     age: 61,
73//! };
74//!
75//! CONFIG.encode(&mut out, &expected)?;
76//! let actual = CONFIG.decode(&out[..])?;
77//!
78//! assert_eq!(expected, actual);
79//! # Ok::<_, musli::descriptive::Error>(())
80//! ```
81//!
82//! <br>
83//!
84//! ## Implementation details
85//!
86//! Each field is prefix *typed* with a single byte tag that describes exactly
87//! the type which is contained in the field.
88
89#![cfg(feature = "descriptive")]
90#![cfg_attr(doc_cfg, doc(cfg(feature = "descriptive")))]
91
92#[cfg(test)]
93mod tests;
94
95mod de;
96mod en;
97mod encoding;
98mod error;
99mod integer_encoding;
100mod tag;
101
102#[cfg(feature = "test")]
103#[cfg_attr(doc_cfg, doc(cfg(feature = "test")))]
104#[doc(hidden)]
105pub mod test;
106
107/// Convenient result alias for use with `musli::descriptive`.
108#[cfg(feature = "alloc")]
109#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
110pub type Result<T, E = Error> = core::result::Result<T, E>;
111
112#[cfg(feature = "alloc")]
113#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
114#[doc(inline)]
115pub use self::encoding::to_vec;
116#[cfg(all(feature = "std", feature = "alloc"))]
117#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "alloc"))))]
118#[doc(inline)]
119pub use self::encoding::to_writer;
120#[doc(inline)]
121pub use self::encoding::{Encoding, OPTIONS};
122#[cfg(feature = "alloc")]
123#[doc(inline)]
124pub use self::encoding::{decode, encode, from_slice, to_fixed_bytes, to_slice};
125#[doc(inline)]
126pub use self::error::Error;
127
128/// The maximum length that can be inlined in the tag without adding additional
129/// data to the wire format.
130#[cfg(test)]
131pub(crate) const MAX_INLINE_LEN: usize = (self::tag::DATA_MASK - 1) as usize;