erased_serde/lib.rs
1//! [![github]](https://github.com/dtolnay/erased-serde) [![crates-io]](https://crates.io/crates/erased-serde) [![docs-rs]](https://docs.rs/erased-serde)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7//! <br>
8//!
9//! This crate provides type-erased versions of Serde's `Serialize`, `Serializer`
10//! and `Deserializer` traits that can be used as [trait objects].
11//!
12//! [trait objects]: https://doc.rust-lang.org/book/trait-objects.html
13//!
14//! The usual Serde `Serialize`, `Serializer` and `Deserializer` traits cannot
15//! be used as trait objects like `&dyn Serialize` or boxed trait objects like
16//! `Box<dyn Serialize>` because of Rust's ["object safety" rules]. In
17//! particular, all three traits contain generic methods which cannot be made
18//! into a trait object.
19//!
20//! ["object safety" rules]: http://huonw.github.io/blog/2015/01/object-safety/
21//!
22//! This library should be considered a low-level building block for interacting
23//! with Serde APIs in an object-safe way. Most use cases will require higher
24//! level functionality such as provided by [`typetag`] which uses this crate
25//! internally.
26//!
27//! [`typetag`]: https://github.com/dtolnay/typetag
28//!
29//! **The traits in this crate work seamlessly with any existing Serde
30//! `Serialize` and `Deserialize` type and any existing Serde `Serializer` and
31//! `Deserializer` format.**
32//!
33//! ## Serialization
34//!
35//! ```rust
36//! use erased_serde::{Serialize, Serializer};
37//! use std::collections::BTreeMap as Map;
38//! use std::io;
39//!
40//! fn main() {
41//! // Construct some serializers.
42//! let json = &mut serde_json::Serializer::new(io::stdout());
43//! let cbor = &mut serde_cbor::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));
44//!
45//! // The values in this map are boxed trait objects. Ordinarily this would not
46//! // be possible with serde::Serializer because of object safety, but type
47//! // erasure makes it possible with erased_serde::Serializer.
48//! let mut formats: Map<&str, Box<dyn Serializer>> = Map::new();
49//! formats.insert("json", Box::new(<dyn Serializer>::erase(json)));
50//! formats.insert("cbor", Box::new(<dyn Serializer>::erase(cbor)));
51//!
52//! // These are boxed trait objects as well. Same thing here - type erasure
53//! // makes this possible.
54//! let mut values: Map<&str, Box<dyn Serialize>> = Map::new();
55//! values.insert("vec", Box::new(vec!["a", "b"]));
56//! values.insert("int", Box::new(65536));
57//!
58//! // Pick a Serializer out of the formats map.
59//! let format = formats.get_mut("json").unwrap();
60//!
61//! // Pick a Serialize out of the values map.
62//! let value = values.get("vec").unwrap();
63//!
64//! // This line prints `["a","b"]` to stdout.
65//! value.erased_serialize(format).unwrap();
66//! }
67//! ```
68//!
69//! ## Deserialization
70//!
71//! ```rust
72//! use erased_serde::Deserializer;
73//! use std::collections::BTreeMap as Map;
74//!
75//! fn main() {
76//! static JSON: &'static [u8] = br#"{"A": 65, "B": 66}"#;
77//! static CBOR: &'static [u8] = &[162, 97, 65, 24, 65, 97, 66, 24, 66];
78//!
79//! // Construct some deserializers.
80//! let json = &mut serde_json::Deserializer::from_slice(JSON);
81//! let cbor = &mut serde_cbor::Deserializer::from_slice(CBOR);
82//!
83//! // The values in this map are boxed trait objects, which is not possible
84//! // with the normal serde::Deserializer because of object safety.
85//! let mut formats: Map<&str, Box<dyn Deserializer>> = Map::new();
86//! formats.insert("json", Box::new(<dyn Deserializer>::erase(json)));
87//! formats.insert("cbor", Box::new(<dyn Deserializer>::erase(cbor)));
88//!
89//! // Pick a Deserializer out of the formats map.
90//! let format = formats.get_mut("json").unwrap();
91//!
92//! let data: Map<String, usize> = erased_serde::deserialize(format).unwrap();
93//!
94//! println!("{}", data["A"] + data["B"]);
95//! }
96//! ```
97
98#![doc(html_root_url = "https://docs.rs/erased-serde/0.4.6")]
99#![no_std]
100#![deny(unsafe_op_in_unsafe_fn)]
101#![allow(
102 clippy::box_collection,
103 clippy::derive_partial_eq_without_eq,
104 clippy::extra_unused_type_parameters,
105 clippy::items_after_statements,
106 clippy::manual_map, // https://github.com/rust-lang/rust-clippy/issues/7820
107 clippy::missing_errors_doc,
108 clippy::needless_doctest_main,
109 clippy::needless_pass_by_ref_mut,
110 clippy::needless_pass_by_value,
111 clippy::semicolon_if_nothing_returned, // https://github.com/rust-lang/rust-clippy/issues/7324
112 clippy::similar_names,
113 clippy::struct_field_names,
114 clippy::unused_self,
115 clippy::wildcard_imports
116)]
117
118extern crate alloc;
119
120#[cfg(feature = "std")]
121extern crate std;
122
123#[macro_use]
124mod macros;
125
126mod any;
127mod de;
128mod error;
129mod features_check;
130mod map;
131mod sealed;
132mod ser;
133
134pub use crate::de::{deserialize, Deserializer};
135pub use crate::error::{Error, Result};
136pub use crate::ser::{serialize, Serialize, Serializer};
137
138// Not public API.
139#[doc(hidden)]
140#[path = "private.rs"]
141pub mod __private;