ntex_util/services/
extensions.rs1use std::{any::Any, any::TypeId, fmt};
2
3#[derive(Default)]
4pub struct Extensions {
6 map: crate::HashMap<TypeId, Box<dyn Any>>,
7}
8
9impl Extensions {
10 #[inline]
12 pub fn new() -> Extensions {
13 Extensions {
14 map: crate::HashMap::default(),
15 }
16 }
17
18 pub fn insert<T: 'static>(&mut self, val: T) -> Option<T> {
22 self.map
23 .insert(TypeId::of::<T>(), Box::new(val))
24 .and_then(|item| item.downcast::<T>().map(|boxed| *boxed).ok())
25 }
26
27 pub fn contains<T: 'static>(&self) -> bool {
29 self.map.contains_key(&TypeId::of::<T>())
30 }
31
32 pub fn get<T: 'static>(&self) -> Option<&T> {
34 self.map
35 .get(&TypeId::of::<T>())
36 .and_then(|boxed| boxed.downcast_ref())
37 }
38
39 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
41 self.map
42 .get_mut(&TypeId::of::<T>())
43 .and_then(|boxed| boxed.downcast_mut())
44 }
45
46 pub fn remove<T: 'static>(&mut self) -> Option<T> {
50 self.map
51 .remove(&TypeId::of::<T>())
52 .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
53 }
54
55 pub fn extend(&mut self, other: Extensions) {
57 self.map.extend(other.map);
58 }
59
60 #[inline]
61 pub fn is_empty(&self) -> bool {
63 self.map.is_empty()
64 }
65
66 #[inline]
68 pub fn clear(&mut self) {
69 self.map.clear();
70 }
71}
72
73impl fmt::Debug for Extensions {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 f.debug_struct("Extensions")
76 .field("size", &self.map.len())
77 .finish()
78 }
79}
80
81#[test]
86fn test_debug() {
87 let mut map = Extensions::new();
88 map.insert::<i8>(123);
89 assert_eq!(format!("{map:?}"), "Extensions { size: 1 }");
90}
91
92#[test]
98fn test_remove() {
99 let mut map = Extensions::new();
100
101 map.insert::<i8>(123);
102 assert!(map.get::<i8>().is_some());
103 assert_eq!(map.insert::<i8>(10), Some(123));
104
105 map.remove::<i8>();
106 assert!(map.get::<i8>().is_none());
107}
108
109#[test]
115fn test_clear() {
116 let mut map = Extensions::new();
117
118 map.insert::<i8>(8);
119 map.insert::<i16>(16);
120 map.insert::<i32>(32);
121
122 assert!(map.contains::<i8>());
123 assert!(map.contains::<i16>());
124 assert!(map.contains::<i32>());
125
126 map.clear();
127
128 assert!(!map.contains::<i8>());
129 assert!(!map.contains::<i16>());
130 assert!(!map.contains::<i32>());
131
132 map.insert::<i8>(10);
133 assert_eq!(*map.get::<i8>().unwrap(), 10);
134}
135
136#[test]
141fn test_integers() {
142 let mut map = Extensions::new();
143
144 map.insert::<i8>(8);
145 map.insert::<i16>(16);
146 map.insert::<i32>(32);
147 map.insert::<i64>(64);
148 map.insert::<i128>(128);
149 map.insert::<u8>(8);
150 map.insert::<u16>(16);
151 map.insert::<u32>(32);
152 map.insert::<u64>(64);
153 map.insert::<u128>(128);
154 assert!(map.get::<i8>().is_some());
155 assert!(map.get::<i16>().is_some());
156 assert!(map.get::<i32>().is_some());
157 assert!(map.get::<i64>().is_some());
158 assert!(map.get::<i128>().is_some());
159 assert!(map.get::<u8>().is_some());
160 assert!(map.get::<u16>().is_some());
161 assert!(map.get::<u32>().is_some());
162 assert!(map.get::<u64>().is_some());
163 assert!(map.get::<u128>().is_some());
164}
165
166#[test]
172fn test_composition() {
173 struct Magi<T>(T);
174
175 struct Madoka {
176 god: bool,
177 }
178
179 struct Homura {
180 attempts: usize,
181 }
182
183 struct Mami {
184 guns: usize,
185 }
186
187 let mut map = Extensions::new();
188
189 map.insert(Magi(Madoka { god: false }));
190 map.insert(Magi(Homura { attempts: 0 }));
191 map.insert(Magi(Mami { guns: 999 }));
192
193 assert!(!map.get::<Magi<Madoka>>().unwrap().0.god);
194 assert_eq!(0, map.get::<Magi<Homura>>().unwrap().0.attempts);
195 assert_eq!(999, map.get::<Magi<Mami>>().unwrap().0.guns);
196}
197
198#[test]
204fn test_extensions() {
205 #[derive(Debug, PartialEq)]
206 struct MyType(i32);
207
208 let mut extensions = Extensions::new();
209
210 extensions.insert(5i32);
211 extensions.insert(MyType(10));
212
213 assert_eq!(extensions.get(), Some(&5i32));
214 assert_eq!(extensions.get_mut(), Some(&mut 5i32));
215
216 assert_eq!(extensions.remove::<i32>(), Some(5i32));
217 assert!(extensions.get::<i32>().is_none());
218
219 assert_eq!(extensions.get::<bool>(), None);
220 assert_eq!(extensions.get(), Some(&MyType(10)));
221}
222
223#[test]
229fn test_extend() {
230 #[derive(Debug, PartialEq)]
231 struct MyType(i32);
232
233 let mut extensions2 = Extensions::new();
234 assert!(extensions2.is_empty());
235 extensions2.insert(MyType(10));
236 assert!(!extensions2.is_empty());
237
238 let mut extensions = Extensions::new();
239 extensions.insert(5i32);
240 extensions.extend(extensions2);
241
242 assert_eq!(extensions.get(), Some(&5i32));
243 assert_eq!(extensions.get_mut(), Some(&mut 5i32));
244
245 assert_eq!(extensions.remove::<i32>(), Some(5i32));
246 assert!(extensions.get::<i32>().is_none());
247
248 assert_eq!(extensions.get::<bool>(), None);
249 assert_eq!(extensions.get(), Some(&MyType(10)));
250}