flow_lib/utils/
extensions.rs

1/*
2Copyright (c) 2017 http-rs authors
3
4Permission is hereby granted, free of charge, to any
5person obtaining a copy of this software and associated
6documentation files (the "Software"), to deal in the
7Software without restriction, including without
8limitation the rights to use, copy, modify, merge,
9publish, distribute, sublicense, and/or sell copies of
10the Software, and to permit persons to whom the Software
11is furnished to do so, subject to the following
12conditions:
13
14The above copyright notice and this permission notice
15shall be included in all copies or substantial portions
16of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
19ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
20TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
21PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
22SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
25IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26DEALINGS IN THE SOFTWARE.
27*/
28
29use std::any::{Any, TypeId};
30use std::collections::HashMap;
31use std::fmt;
32use std::hash::{BuildHasherDefault, Hasher};
33
34type AnyMap = HashMap<TypeId, Box<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>;
35
36#[derive(Default)]
37struct IdHasher(u64);
38
39impl Hasher for IdHasher {
40    fn write(&mut self, _: &[u8]) {
41        unreachable!("TypeId calls write_u64");
42    }
43
44    #[inline]
45    fn write_u64(&mut self, id: u64) {
46        self.0 = id;
47    }
48
49    #[inline]
50    fn finish(&self) -> u64 {
51        self.0
52    }
53}
54
55#[derive(Default)]
56pub struct Extensions {
57    // If extensions are never used, no need to carry around an empty HashMap.
58    // That's 3 words. Instead, this is only 1 word.
59    map: Option<Box<AnyMap>>,
60}
61
62impl Extensions {
63    /// Create an empty `Extensions`.
64    #[inline]
65    pub fn new() -> Extensions {
66        Extensions { map: None }
67    }
68
69    /// Insert a type into this `Extensions`.
70    ///
71    /// If a extension of this type already existed, it will
72    /// be returned.
73    ///
74    /// # Example
75    ///
76    /// ```
77    /// use flow_lib::utils::Extensions;
78    /// let mut ext = Extensions::new();
79    /// assert!(ext.insert(5i32).is_none());
80    /// assert!(ext.insert(4u8).is_none());
81    /// assert_eq!(ext.insert(9i32), Some(5i32));
82    /// ```
83    pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
84        self.map
85            .get_or_insert_with(Box::<HashMap<TypeId, Box<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>>::default)
86            .insert(TypeId::of::<T>(), Box::new(val))
87            .and_then(|boxed| {
88                (boxed as Box<dyn Any + 'static>)
89                    .downcast()
90                    .ok()
91                    .map(|boxed| *boxed)
92            })
93    }
94
95    /// Get a reference to a type previously inserted on this `Extensions`.
96    ///
97    /// # Example
98    ///
99    /// ```
100    /// use flow_lib::utils::Extensions;
101    /// let mut ext = Extensions::new();
102    /// assert!(ext.get::<i32>().is_none());
103    /// ext.insert(5i32);
104    ///
105    /// assert_eq!(ext.get::<i32>(), Some(&5i32));
106    /// ```
107    pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
108        self.map
109            .as_ref()
110            .and_then(|map| map.get(&TypeId::of::<T>()))
111            .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
112    }
113
114    /// Get a mutable reference to a type previously inserted on this `Extensions`.
115    ///
116    /// # Example
117    ///
118    /// ```
119    /// use flow_lib::utils::Extensions;
120    /// let mut ext = Extensions::new();
121    /// ext.insert(String::from("Hello"));
122    /// ext.get_mut::<String>().unwrap().push_str(" World");
123    ///
124    /// assert_eq!(ext.get::<String>().unwrap(), "Hello World");
125    /// ```
126    pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
127        self.map
128            .as_mut()
129            .and_then(|map| map.get_mut(&TypeId::of::<T>()))
130            .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
131    }
132
133    /// Remove a type from this `Extensions`.
134    ///
135    /// If a extension of this type existed, it will be returned.
136    ///
137    /// # Example
138    ///
139    /// ```
140    /// use flow_lib::utils::Extensions;
141    /// let mut ext = Extensions::new();
142    /// ext.insert(5i32);
143    /// assert_eq!(ext.remove::<i32>(), Some(5i32));
144    /// assert!(ext.get::<i32>().is_none());
145    /// ```
146    pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
147        self.map
148            .as_mut()
149            .and_then(|map| map.remove(&TypeId::of::<T>()))
150            .and_then(|boxed| {
151                (boxed as Box<dyn Any + 'static>)
152                    .downcast()
153                    .ok()
154                    .map(|boxed| *boxed)
155            })
156    }
157
158    /// Clear the `Extensions` of all inserted extensions.
159    ///
160    /// # Example
161    ///
162    /// ```
163    /// use flow_lib::utils::Extensions;
164    /// let mut ext = Extensions::new();
165    /// ext.insert(5i32);
166    /// ext.clear();
167    ///
168    /// assert!(ext.get::<i32>().is_none());
169    /// ```
170    #[inline]
171    pub fn clear(&mut self) {
172        if let Some(ref mut map) = self.map {
173            map.clear();
174        }
175    }
176
177    /// Check whether the extension set is empty or not.
178    ///
179    /// # Example
180    ///
181    /// ```
182    /// use flow_lib::utils::Extensions;
183    /// let mut ext = Extensions::new();
184    /// assert!(ext.is_empty());
185    /// ext.insert(5i32);
186    /// assert!(!ext.is_empty());
187    /// ```
188    #[inline]
189    pub fn is_empty(&self) -> bool {
190        self.map.as_ref().is_none_or(|map| map.is_empty())
191    }
192
193    /// Get the numer of extensions available.
194    ///
195    /// # Example
196    ///
197    /// ```
198    /// use flow_lib::utils::Extensions;
199    /// let mut ext = Extensions::new();
200    /// assert_eq!(ext.len(), 0);
201    /// ext.insert(5i32);
202    /// assert_eq!(ext.len(), 1);
203    /// ```
204    #[inline]
205    pub fn len(&self) -> usize {
206        self.map.as_ref().map_or(0, |map| map.len())
207    }
208
209    /// Extends `self` with another `Extensions`.
210    ///
211    /// If an instance of a specific type exists in both, the one in `self` is overwritten with the
212    /// one from `other`.
213    ///
214    /// # Example
215    ///
216    /// ```
217    /// use flow_lib::utils::Extensions;
218    /// let mut ext_a = Extensions::new();
219    /// ext_a.insert(8u8);
220    /// ext_a.insert(16u16);
221    ///
222    /// let mut ext_b = Extensions::new();
223    /// ext_b.insert(4u8);
224    /// ext_b.insert("hello");
225    ///
226    /// ext_a.extend(ext_b);
227    /// assert_eq!(ext_a.len(), 3);
228    /// assert_eq!(ext_a.get::<u8>(), Some(&4u8));
229    /// assert_eq!(ext_a.get::<u16>(), Some(&16u16));
230    /// assert_eq!(ext_a.get::<&'static str>().copied(), Some("hello"));
231    /// ```
232    pub fn extend(&mut self, other: Self) {
233        if let Some(other) = other.map {
234            if let Some(map) = &mut self.map {
235                map.extend(*other);
236            } else {
237                self.map = Some(other);
238            }
239        }
240    }
241}
242
243impl fmt::Debug for Extensions {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        f.debug_struct("Extensions").finish()
246    }
247}
248
249#[cfg(test)]
250mod tests {
251    use super::*;
252
253    #[test]
254    fn test_extensions() {
255        #[derive(Debug, PartialEq)]
256        struct MyType(i32);
257
258        let mut extensions = Extensions::new();
259
260        extensions.insert(5i32);
261        extensions.insert(MyType(10));
262
263        assert_eq!(extensions.get(), Some(&5i32));
264        assert_eq!(extensions.get_mut(), Some(&mut 5i32));
265
266        assert_eq!(extensions.remove::<i32>(), Some(5i32));
267        assert!(extensions.get::<i32>().is_none());
268
269        assert_eq!(extensions.get::<bool>(), None);
270        assert_eq!(extensions.get(), Some(&MyType(10)));
271    }
272}