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;