type_reg/
lib.rs

1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
2
3//! Serializable map of any type.
4//!
5//! This library provides a map that can store any serializable type, and
6//! retrieve it as the strong type. Serialization and deserialization is also
7//! done without requiring the consumer to implement custom serde logic.
8//!
9//! ## Usage
10//!
11//! Add the following to `Cargo.toml`
12//!
13//! ```toml
14//! type_reg = { version = "0.9.0", features = ["tagged"] }
15//! type_reg = { version = "0.9.0", features = ["untagged"] }
16//!
17//! # Values must impl Debug, and TypeMap's Debug impl will
18//! # print the debug string of each value.
19//! type_reg = { version = "0.9.0", features = ["debug"] }
20//!
21//! # Use insertion order for TypeMap and TypeReg iteration order.
22//! type_reg = { version = "0.9.0", features = ["ordered"] }
23//! ```
24//!
25//! ### Untagged Type Registry
26//!
27//! #### Serialization
28//!
29//! ```rust
30//! # #![allow(clippy::needless_doctest_main)]
31//! use serde::{Deserialize, Serialize};
32//! use type_reg::untagged::TypeMap;
33//!
34//! #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
35//! struct A(u32);
36//!
37//! fn main() {
38//!     let mut type_map = TypeMap::new();
39//!     type_map.insert("one", 1u32);
40//!     type_map.insert("two", 2u64);
41//!     type_map.insert("three", A(3));
42//!
43//!     println!("{}", serde_yaml_ng::to_string(&type_map).unwrap());
44//!
45//!     // ---
46//!     // two: 2
47//!     // one: 1
48//!     // three: 3
49//! }
50//! ```
51//!
52//! #### Deserialization
53//!
54//! ```rust
55//! # #![allow(clippy::needless_doctest_main)]
56//! use serde::{Deserialize, Serialize};
57//! use type_reg::untagged::{TypeMap, TypeReg};
58//!
59//! #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
60//! struct A(u32);
61//!
62//! fn main() {
63//!     let mut type_reg = TypeReg::<String>::new();
64//!     type_reg.register::<u32>(String::from("one"));
65//!     type_reg.register::<u64>(String::from("two"));
66//!     type_reg.register::<A>(String::from("three"));
67//!
68//!     let serialized = "---\n\
69//!         one: 1\n\
70//!         two: 2\n\
71//!         three: 3\n\
72//!         ";
73//!
74//!     let deserializer = serde_yaml_ng::Deserializer::from_str(serialized);
75//!     let type_map: TypeMap<String> = type_reg.deserialize_map(deserializer).unwrap();
76//!
77//!     let data_u32 = type_map.get::<u32, _>("one").copied().unwrap();
78//!     let data_u64 = type_map.get::<u64, _>("two").copied().unwrap();
79//!     let data_a = type_map.get::<A, _>("three").copied().unwrap();
80//!
81//!     println!("{data_u32}, {data_u64}, {data_a:?}");
82//!
83//!     // 1, 2, A(3)
84//! }
85//! ```
86//!
87//! ### Tagged Type Registry
88//!
89//! ⚠️ **Note:** This uses [`std::any::type_name`] internally, which is not
90//! stable.
91//!
92//! #### Serialization
93//!
94//! ```rust
95//! # #![allow(clippy::needless_doctest_main)]
96//! use serde::{Deserialize, Serialize};
97//! use type_reg::tagged::TypeMap;
98//!
99//! #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
100//! struct A(u32);
101//!
102//! fn main() {
103//!     let mut type_map = TypeMap::new();
104//!     type_map.insert("one", 1u32);
105//!     type_map.insert("two", 2u64);
106//!     type_map.insert("three", A(3));
107//!
108//!     println!("{}", serde_yaml_ng::to_string(&type_map).unwrap());
109//!
110//!     // ---
111//!     // one:
112//!     //   u32: 1
113//!     // three:
114//!     //   "tagged_serialize::A": 3
115//!     // two:
116//!     //   u64: 2
117//! }
118//! ```
119//!
120//! #### Deserialization
121//!
122//! ```rust
123//! # #![allow(clippy::needless_doctest_main)]
124//! use serde::{Deserialize, Serialize};
125//! use type_reg::tagged::{TypeMap, TypeReg};
126//!
127//! #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
128//! struct A(u32);
129//!
130//! fn main() {
131//!     let mut type_reg = TypeReg::new();
132//!     type_reg.register::<u32>();
133//!     type_reg.register::<u64>();
134//!     type_reg.register::<A>();
135//!
136//!     let serialized = "---\n\
137//!         one:   { u32: 1 }\n\
138//!         two:   { u64: 2 }\n\
139//!         three: { 'rust_out::A': 3 }\n\
140//!         ";
141//!
142//!     let deserializer = serde_yaml_ng::Deserializer::from_str(serialized);
143//!     let type_map: TypeMap<String> = type_reg.deserialize_map(deserializer).unwrap();
144//!
145//!     let data_u32 = type_map.get::<u32, _>("one").copied().unwrap();
146//!     let data_u64 = type_map.get::<u64, _>("two").copied().unwrap();
147//!     let data_a = type_map.get::<A, _>("three").copied().unwrap();
148//!
149//!     println!("{data_u32}, {data_u64}, {data_a:?}");
150//!
151//!     // 1, 2, A(3)
152//! }
153//! ```
154
155#[cfg(any(feature = "tagged", feature = "untagged"))]
156pub mod common;
157#[cfg(feature = "tagged")]
158pub mod tagged;
159#[cfg(feature = "untagged")]
160pub mod untagged;
161
162pub use crate::type_name_lit::TypeNameLit;
163
164mod type_name_lit;
165
166// This is used in `Debug` impls, but for some reason rustc warns the fields
167// are not used.
168#[allow(dead_code)]
169#[derive(Debug)]
170pub(crate) struct TypedValue<'a> {
171    r#type: TypeNameLit,
172    value: &'a dyn std::fmt::Debug,
173}