nylon_ring_host/extensions.rs
1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::{BuildHasherDefault, Hasher};
5
6type AnyMap = HashMap<TypeId, Box<dyn AnyClone + Send + Sync>, BuildHasherDefault<IdHasher>>;
7
8// With TypeIds as keys, there's no need to hash them. They are already hashes
9// themselves, coming from the compiler. The IdHasher just holds the u64 of
10// the TypeId, and then returns it, instead of doing any bit fiddling.
11#[derive(Default)]
12struct IdHasher(u64);
13
14impl Hasher for IdHasher {
15 fn write(&mut self, _: &[u8]) {
16 unreachable!("TypeId calls write_u64");
17 }
18
19 #[inline]
20 fn write_u64(&mut self, id: u64) {
21 self.0 = id;
22 }
23
24 #[inline]
25 fn finish(&self) -> u64 {
26 self.0
27 }
28}
29
30/// A type map of protocol extensions.
31///
32/// `Extensions` can be used by `HighLevelRequest` to store
33/// extra data derived from the underlying protocol.
34#[derive(Clone, Default)]
35pub struct Extensions {
36 // If extensions are never used, no need to carry around an empty HashMap.
37 // That's 3 words. Instead, this is only 1 word.
38 map: Option<Box<AnyMap>>,
39}
40
41impl Extensions {
42 /// Create an empty `Extensions`.
43 #[inline]
44 pub fn new() -> Extensions {
45 Extensions { map: None }
46 }
47
48 /// Insert a type into this `Extensions`.
49 ///
50 /// If a extension of this type already existed, it will
51 /// be returned and replaced with the new one.
52 ///
53 /// # Example
54 ///
55 /// ```
56 /// # use nylon_ring_host::Extensions;
57 /// let mut ext = Extensions::new();
58 /// assert!(ext.insert(5i32).is_none());
59 /// assert!(ext.insert(4u8).is_none());
60 /// assert_eq!(ext.insert(9i32), Some(5i32));
61 /// ```
62 pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
63 self.map
64 .get_or_insert_with(Box::default)
65 .insert(TypeId::of::<T>(), Box::new(val))
66 .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
67 }
68
69 /// Get a reference to a type previously inserted on this `Extensions`.
70 ///
71 /// # Example
72 ///
73 /// ```
74 /// # use nylon_ring_host::Extensions;
75 /// let mut ext = Extensions::new();
76 /// assert!(ext.get::<i32>().is_none());
77 /// ext.insert(5i32);
78 ///
79 /// assert_eq!(ext.get::<i32>(), Some(&5i32));
80 /// ```
81 pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
82 self.map
83 .as_ref()
84 .and_then(|map| map.get(&TypeId::of::<T>()))
85 .and_then(|boxed| (**boxed).as_any().downcast_ref())
86 }
87
88 /// Get a mutable reference to a type previously inserted on this `Extensions`.
89 ///
90 /// # Example
91 ///
92 /// ```
93 /// # use nylon_ring_host::Extensions;
94 /// let mut ext = Extensions::new();
95 /// ext.insert(String::from("Hello"));
96 /// ext.get_mut::<String>().unwrap().push_str(" World");
97 ///
98 /// assert_eq!(ext.get::<String>().unwrap(), "Hello World");
99 /// ```
100 pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
101 self.map
102 .as_mut()
103 .and_then(|map| map.get_mut(&TypeId::of::<T>()))
104 .and_then(|boxed| (**boxed).as_any_mut().downcast_mut())
105 }
106
107 /// Get a mutable reference to a type, inserting `value` if not already present on this
108 /// `Extensions`.
109 ///
110 /// # Example
111 ///
112 /// ```
113 /// # use nylon_ring_host::Extensions;
114 /// let mut ext = Extensions::new();
115 /// *ext.get_or_insert(1i32) += 2;
116 ///
117 /// assert_eq!(*ext.get::<i32>().unwrap(), 3);
118 /// ```
119 pub fn get_or_insert<T: Clone + Send + Sync + 'static>(&mut self, value: T) -> &mut T {
120 self.get_or_insert_with(|| value)
121 }
122
123 /// Get a mutable reference to a type, inserting the value created by `f` if not already present
124 /// on this `Extensions`.
125 ///
126 /// # Example
127 ///
128 /// ```
129 /// # use nylon_ring_host::Extensions;
130 /// let mut ext = Extensions::new();
131 /// *ext.get_or_insert_with(|| 1i32) += 2;
132 ///
133 /// assert_eq!(*ext.get::<i32>().unwrap(), 3);
134 /// ```
135 pub fn get_or_insert_with<T: Clone + Send + Sync + 'static, F: FnOnce() -> T>(
136 &mut self,
137 f: F,
138 ) -> &mut T {
139 let out = self
140 .map
141 .get_or_insert_with(Box::default)
142 .entry(TypeId::of::<T>())
143 .or_insert_with(|| Box::new(f()));
144
145 // Safety: TypeId::of::<T>() guarantees this entry contains type T,
146 // so the downcast cannot fail. Using expect instead of unwrap for clarity.
147 (**out)
148 .as_any_mut()
149 .downcast_mut()
150 .expect("TypeId mismatch: this is a bug in Extensions implementation")
151 }
152
153 /// Get a mutable reference to a type, inserting the type's default value if not already present
154 /// on this `Extensions`.
155 ///
156 /// # Example
157 ///
158 /// ```
159 /// # use nylon_ring_host::Extensions;
160 /// let mut ext = Extensions::new();
161 /// *ext.get_or_insert_default::<i32>() += 2;
162 ///
163 /// assert_eq!(*ext.get::<i32>().unwrap(), 2);
164 /// ```
165 pub fn get_or_insert_default<T: Default + Clone + Send + Sync + 'static>(&mut self) -> &mut T {
166 self.get_or_insert_with(T::default)
167 }
168
169 /// Remove a type from this `Extensions`.
170 ///
171 /// If a extension of this type existed, it will be returned.
172 ///
173 /// # Example
174 ///
175 /// ```
176 /// # use nylon_ring_host::Extensions;
177 /// let mut ext = Extensions::new();
178 /// ext.insert(5i32);
179 /// assert_eq!(ext.remove::<i32>(), Some(5i32));
180 /// assert!(ext.get::<i32>().is_none());
181 /// ```
182 pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
183 self.map
184 .as_mut()
185 .and_then(|map| map.remove(&TypeId::of::<T>()))
186 .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
187 }
188
189 /// Clear the `Extensions` of all inserted extensions.
190 ///
191 /// # Example
192 ///
193 /// ```
194 /// # use nylon_ring_host::Extensions;
195 /// let mut ext = Extensions::new();
196 /// ext.insert(5i32);
197 /// ext.clear();
198 ///
199 /// assert!(ext.get::<i32>().is_none());
200 /// ```
201 #[inline]
202 pub fn clear(&mut self) {
203 if let Some(ref mut map) = self.map {
204 map.clear();
205 }
206 }
207
208 /// Check whether the extension set is empty or not.
209 ///
210 /// # Example
211 ///
212 /// ```
213 /// # use nylon_ring_host::Extensions;
214 /// let mut ext = Extensions::new();
215 /// assert!(ext.is_empty());
216 /// ext.insert(5i32);
217 /// assert!(!ext.is_empty());
218 /// ```
219 #[inline]
220 pub fn is_empty(&self) -> bool {
221 self.map.as_ref().is_none_or(|map| map.is_empty())
222 }
223
224 /// Get the number of extensions available.
225 ///
226 /// # Example
227 ///
228 /// ```
229 /// # use nylon_ring_host::Extensions;
230 /// let mut ext = Extensions::new();
231 /// assert_eq!(ext.len(), 0);
232 /// ext.insert(5i32);
233 /// assert_eq!(ext.len(), 1);
234 /// ```
235 #[inline]
236 pub fn len(&self) -> usize {
237 self.map.as_ref().map_or(0, |map| map.len())
238 }
239
240 /// Extends `self` with another `Extensions`.
241 ///
242 /// If an instance of a specific type exists in both, the one in `self` is overwritten with the
243 /// one from `other`.
244 ///
245 /// # Example
246 ///
247 /// ```
248 /// # use nylon_ring_host::Extensions;
249 /// let mut ext_a = Extensions::new();
250 /// ext_a.insert(8u8);
251 /// ext_a.insert(16u16);
252 ///
253 /// let mut ext_b = Extensions::new();
254 /// ext_b.insert(4u8);
255 /// ext_b.insert("hello");
256 ///
257 /// ext_a.extend(ext_b);
258 /// assert_eq!(ext_a.len(), 3);
259 /// assert_eq!(ext_a.get::<u8>(), Some(&4u8));
260 /// assert_eq!(ext_a.get::<u16>(), Some(&16u16));
261 /// assert_eq!(ext_a.get::<&'static str>().copied(), Some("hello"));
262 /// ```
263 pub fn extend(&mut self, other: Self) {
264 if let Some(other) = other.map {
265 if let Some(map) = &mut self.map {
266 map.extend(*other);
267 } else {
268 self.map = Some(other);
269 }
270 }
271 }
272}
273
274impl fmt::Debug for Extensions {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 f.debug_struct("Extensions").finish()
277 }
278}
279
280trait AnyClone: Any {
281 fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync>;
282 fn as_any(&self) -> &dyn Any;
283 fn as_any_mut(&mut self) -> &mut dyn Any;
284 fn into_any(self: Box<Self>) -> Box<dyn Any>;
285}
286
287impl<T: Clone + Send + Sync + 'static> AnyClone for T {
288 fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync> {
289 Box::new(self.clone())
290 }
291
292 fn as_any(&self) -> &dyn Any {
293 self
294 }
295
296 fn as_any_mut(&mut self) -> &mut dyn Any {
297 self
298 }
299
300 fn into_any(self: Box<Self>) -> Box<dyn Any> {
301 self
302 }
303}
304
305impl Clone for Box<dyn AnyClone + Send + Sync> {
306 fn clone(&self) -> Self {
307 (**self).clone_box()
308 }
309}
310
311#[cfg(test)]
312mod tests {
313 use super::Extensions;
314
315 #[test]
316 fn test_extensions() {
317 #[derive(Clone, Debug, PartialEq)]
318 struct MyType(i32);
319
320 let mut extensions = Extensions::new();
321
322 extensions.insert(5i32);
323 extensions.insert(MyType(10));
324
325 assert_eq!(extensions.get(), Some(&5i32));
326 assert_eq!(extensions.get_mut(), Some(&mut 5i32));
327
328 let ext2 = extensions.clone();
329
330 assert_eq!(extensions.remove::<i32>(), Some(5i32));
331 assert!(extensions.get::<i32>().is_none());
332
333 // clone still has it
334 assert_eq!(ext2.get(), Some(&5i32));
335 assert_eq!(ext2.get(), Some(&MyType(10)));
336
337 assert_eq!(extensions.get::<bool>(), None);
338 assert_eq!(extensions.get(), Some(&MyType(10)));
339 }
340}