requiem_http/
extensions.rs

1use std::any::{Any, TypeId};
2use std::fmt;
3
4use fxhash::FxHashMap;
5
6#[derive(Default)]
7/// A type map of request extensions.
8pub struct Extensions {
9    map: FxHashMap<TypeId, Box<dyn Any>>,
10}
11
12impl Extensions {
13    /// Create an empty `Extensions`.
14    #[inline]
15    pub fn new() -> Extensions {
16        Extensions {
17            map: FxHashMap::default(),
18        }
19    }
20
21    /// Insert a type into this `Extensions`.
22    ///
23    /// If a extension of this type already existed, it will
24    /// be returned.
25    pub fn insert<T: 'static>(&mut self, val: T) {
26        self.map.insert(TypeId::of::<T>(), Box::new(val));
27    }
28
29    /// Check if container contains entry
30    pub fn contains<T: 'static>(&self) -> bool {
31        self.map.get(&TypeId::of::<T>()).is_some()
32    }
33
34    /// Get a reference to a type previously inserted on this `Extensions`.
35    pub fn get<T: 'static>(&self) -> Option<&T> {
36        self.map
37            .get(&TypeId::of::<T>())
38            .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
39    }
40
41    /// Get a mutable reference to a type previously inserted on this `Extensions`.
42    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
43        self.map
44            .get_mut(&TypeId::of::<T>())
45            .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
46    }
47
48    /// Remove a type from this `Extensions`.
49    ///
50    /// If a extension of this type existed, it will be returned.
51    pub fn remove<T: 'static>(&mut self) -> Option<T> {
52        self.map.remove(&TypeId::of::<T>()).and_then(|boxed| {
53            (boxed as Box<dyn Any + 'static>)
54                .downcast()
55                .ok()
56                .map(|boxed| *boxed)
57        })
58    }
59
60    /// Clear the `Extensions` of all inserted extensions.
61    #[inline]
62    pub fn clear(&mut self) {
63        self.map.clear();
64    }
65}
66
67impl fmt::Debug for Extensions {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        f.debug_struct("Extensions").finish()
70    }
71}
72
73#[test]
74fn test_extensions() {
75    #[derive(Debug, PartialEq)]
76    struct MyType(i32);
77
78    let mut extensions = Extensions::new();
79
80    extensions.insert(5i32);
81    extensions.insert(MyType(10));
82
83    assert_eq!(extensions.get(), Some(&5i32));
84    assert_eq!(extensions.get_mut(), Some(&mut 5i32));
85
86    assert_eq!(extensions.remove::<i32>(), Some(5i32));
87    assert!(extensions.get::<i32>().is_none());
88
89    assert_eq!(extensions.get::<bool>(), None);
90    assert_eq!(extensions.get(), Some(&MyType(10)));
91}