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