type_registry/
lib.rs

1//! A library for statically registering types.
2//! 
3//! E.g.:
4//!
5//! ```
6//! use type_registry::{registration, Registered, Registration, Registry, RegistryExt};
7//!
8//! struct StringAnalyserTypeInfo {
9//!     analyse: fn(&str) -> Option<usize>
10//! }
11//!
12//! struct StringAnalyserRegistry;
13//!
14//! impl Registry for StringAnalyserRegistry {
15//!     type TypeInfo = StringAnalyserTypeInfo;
16//! 
17//!     fn name() -> &'static str { 
18//!         "String Analysers"
19//!     }
20//! }
21//!
22//! struct LenAnalyser;
23//!
24//! unsafe impl Registered<StringAnalyserRegistry> for LenAnalyser {
25//!     fn register() -> Registration<StringAnalyserRegistry, Self> {
26//!         // NOTE: Can't use generic 'Self' type here
27//!         registration!(StringAnalyserRegistry, LenAnalyser)
28//!     }
29//!
30//!     fn type_info() -> &'static StringAnalyserTypeInfo {
31//!         static TYPE_INFO: StringAnalyserTypeInfo = StringAnalyserTypeInfo {
32//!             analyse: |string| Some(string.len())
33//!         };
34//!
35//!         &TYPE_INFO
36//!     }
37//! }
38//!
39//! struct NumFinderAnalyser;
40//!
41//! unsafe impl Registered<StringAnalyserRegistry> for NumFinderAnalyser {
42//!     fn register() -> Registration<StringAnalyserRegistry, Self> {
43//!         // NOTE: Can't use generic 'Self' type here
44//!         registration!(StringAnalyserRegistry, NumFinderAnalyser)
45//!     }
46//!
47//!     fn type_info() -> &'static StringAnalyserTypeInfo {
48//!         fn is_digit(c: char) -> bool {
49//!             c.is_ascii_digit()
50//!         }
51//!         static TYPE_INFO: StringAnalyserTypeInfo = StringAnalyserTypeInfo {
52//!             analyse: |string| {
53//!                 let start = string.find(is_digit)?;
54//!                 let end = string.rfind(is_digit)?;
55//!                 std::str::FromStr::from_str(&string[start..=end]).ok()
56//!             }
57//!         };
58//!
59//!         &TYPE_INFO
60//!     }
61//! }
62//!
63//! fn main() {
64//!     for (_id, entry) in StringAnalyserRegistry::iter() {
65//!         assert_eq!((entry.type_info().analyse)("I'm 22 characters long"), Some(22))
66//!     }
67//! }
68//! ```
69//!
70//! If you want all types in a registry to implement some trait, you can statically ensure this
71//! by making the [type-info](Registry::TypeInfo) only constructable for types that implement the
72//! trait. Furthermore, if you require all implementors of the trait to be registered, you can
73//! add a [Registered] bound to the trait.
74//!
75//! E.g. similar to the example above, but with a `StringAnalyser` trait:
76//!
77//! ```
78//! use type_registry::{register, Registered, Registration, Registry, RegistryExt};
79//!
80//! trait StringAnalyser: Registered<StringAnalyserRegistry> {
81//!     fn analyse(string: &str) -> Option<usize>;
82//! }
83//!
84//! struct StringAnalyserTypeInfo {
85//!     analyse: fn(&str) -> Option<usize>
86//! }
87//!
88//! impl StringAnalyserTypeInfo {
89//!     pub const fn new<T: StringAnalyser>() -> Self {
90//!         Self {
91//!             analyse: T::analyse
92//!         }
93//!     }
94//! }
95//!
96//! struct StringAnalyserRegistry;
97//!
98//! impl Registry for StringAnalyserRegistry {
99//!     type TypeInfo = StringAnalyserTypeInfo;
100//!
101//!     fn name() -> &'static str {
102//!         "String Analysers"
103//!     }
104//! }
105//!
106//! #[register(StringAnalyserRegistry)]
107//! struct LenAnalyser;
108//!
109//! impl StringAnalyser for LenAnalyser {
110//!     fn analyse(string: &str) -> Option<usize> {
111//!         Some(string.len())
112//!     }
113//! }
114//!
115//! #[register(StringAnalyserRegistry)]
116//! struct NumFinderAnalyser;
117//!
118//! impl NumFinderAnalyser {
119//!     fn is_digit(c: char) -> bool {
120//!         c.is_ascii_digit()
121//!     }
122//! }
123//!
124//! impl StringAnalyser for NumFinderAnalyser {
125//!     fn analyse(string: &str) -> Option<usize> {
126//!         let start = string.find(Self::is_digit)?;
127//!         let end = string.rfind(Self::is_digit)?;
128//!         std::str::FromStr::from_str(&string[start..=end]).ok()
129//!     }
130//! }
131//!
132//! fn main() {
133//!     for (_id, entry) in StringAnalyserRegistry::iter() {
134//!         assert_eq!((entry.type_info().analyse)("I'm 22 characters long"), Some(22))
135//!     }
136//! }
137//! ```
138
139mod logical;
140pub use logical::*;
141
142#[doc(hidden)]
143pub mod raw;
144pub use raw::RegistryId;
145
146#[doc(hidden)]
147pub mod reexports {
148    pub use linkme;
149}
150
151#[cfg(feature = "macro")]
152pub use type_registry_register_macro::register;