1 use std::any::{Any, TypeId};
2 use std::collections::HashMap;
3 use std::fmt;
4 use std::hash::{BuildHasherDefault, Hasher};
5 
6 type AnyMap = HashMap<TypeId, Box<dyn Any + 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)]
12 struct IdHasher(u64);
13 
14 impl Hasher for IdHasher {
write(&mut self, _: &[u8])15     fn write(&mut self, _: &[u8]) {
16         unreachable!("TypeId calls write_u64");
17     }
18 
19     #[inline]
write_u64(&mut self, id: u64)20     fn write_u64(&mut self, id: u64) {
21         self.0 = id;
22     }
23 
24     #[inline]
finish(&self) -> u6425     fn finish(&self) -> u64 {
26         self.0
27     }
28 }
29 
30 /// A type map of protocol extensions.
31 ///
32 /// `Extensions` can be used by `Request` and `Response` to store
33 /// extra data derived from the underlying protocol.
34 #[derive(Default)]
35 pub 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 
41 impl Extensions {
42     /// Create an empty `Extensions`.
43     #[inline]
new() -> Extensions44     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.
52     ///
53     /// # Example
54     ///
55     /// ```
56     /// # use http::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     /// ```
insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T>62     pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
63         self.map
64             .get_or_insert_with(|| Box::new(HashMap::default()))
65             .insert(TypeId::of::<T>(), Box::new(val))
66             .and_then(|boxed| {
67                 (boxed as Box<dyn Any + 'static>)
68                     .downcast()
69                     .ok()
70                     .map(|boxed| *boxed)
71             })
72     }
73 
74     /// Get a reference to a type previously inserted on this `Extensions`.
75     ///
76     /// # Example
77     ///
78     /// ```
79     /// # use http::Extensions;
80     /// let mut ext = Extensions::new();
81     /// assert!(ext.get::<i32>().is_none());
82     /// ext.insert(5i32);
83     ///
84     /// assert_eq!(ext.get::<i32>(), Some(&5i32));
85     /// ```
get<T: Send + Sync + 'static>(&self) -> Option<&T>86     pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
87         self.map
88             .as_ref()
89             .and_then(|map| map.get(&TypeId::of::<T>()))
90             .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
91     }
92 
93     /// Get a mutable reference to a type previously inserted on this `Extensions`.
94     ///
95     /// # Example
96     ///
97     /// ```
98     /// # use http::Extensions;
99     /// let mut ext = Extensions::new();
100     /// ext.insert(String::from("Hello"));
101     /// ext.get_mut::<String>().unwrap().push_str(" World");
102     ///
103     /// assert_eq!(ext.get::<String>().unwrap(), "Hello World");
104     /// ```
get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T>105     pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
106         self.map
107             .as_mut()
108             .and_then(|map| map.get_mut(&TypeId::of::<T>()))
109             .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
110     }
111 
112     /// Remove a type from this `Extensions`.
113     ///
114     /// If a extension of this type existed, it will be returned.
115     ///
116     /// # Example
117     ///
118     /// ```
119     /// # use http::Extensions;
120     /// let mut ext = Extensions::new();
121     /// ext.insert(5i32);
122     /// assert_eq!(ext.remove::<i32>(), Some(5i32));
123     /// assert!(ext.get::<i32>().is_none());
124     /// ```
remove<T: Send + Sync + 'static>(&mut self) -> Option<T>125     pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
126         self.map
127             .as_mut()
128             .and_then(|map| map.remove(&TypeId::of::<T>()))
129             .and_then(|boxed| {
130                 (boxed as Box<dyn Any + 'static>)
131                     .downcast()
132                     .ok()
133                     .map(|boxed| *boxed)
134             })
135     }
136 
137     /// Clear the `Extensions` of all inserted extensions.
138     ///
139     /// # Example
140     ///
141     /// ```
142     /// # use http::Extensions;
143     /// let mut ext = Extensions::new();
144     /// ext.insert(5i32);
145     /// ext.clear();
146     ///
147     /// assert!(ext.get::<i32>().is_none());
148     /// ```
149     #[inline]
clear(&mut self)150     pub fn clear(&mut self) {
151         if let Some(ref mut map) = self.map {
152             map.clear();
153         }
154     }
155 
156     /// Check whether the extension set is empty or not.
157     ///
158     /// # Example
159     ///
160     /// ```
161     /// # use http::Extensions;
162     /// let mut ext = Extensions::new();
163     /// assert!(ext.is_empty());
164     /// ext.insert(5i32);
165     /// assert!(!ext.is_empty());
166     /// ```
167     #[inline]
is_empty(&self) -> bool168     pub fn is_empty(&self) -> bool {
169         self.map
170             .as_ref()
171             .map_or(true, |map| map.is_empty())
172     }
173 
174     /// Get the numer of extensions available.
175     ///
176     /// # Example
177     ///
178     /// ```
179     /// # use http::Extensions;
180     /// let mut ext = Extensions::new();
181     /// assert_eq!(ext.len(), 0);
182     /// ext.insert(5i32);
183     /// assert_eq!(ext.len(), 1);
184     /// ```
185     #[inline]
len(&self) -> usize186     pub fn len(&self) -> usize {
187         self.map
188             .as_ref()
189             .map_or(0, |map| map.len())
190     }
191 }
192 
193 impl fmt::Debug for Extensions {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result194     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195         f.debug_struct("Extensions").finish()
196     }
197 }
198 
199 #[test]
test_extensions()200 fn test_extensions() {
201     #[derive(Debug, PartialEq)]
202     struct MyType(i32);
203 
204     let mut extensions = Extensions::new();
205 
206     extensions.insert(5i32);
207     extensions.insert(MyType(10));
208 
209     assert_eq!(extensions.get(), Some(&5i32));
210     assert_eq!(extensions.get_mut(), Some(&mut 5i32));
211 
212     assert_eq!(extensions.remove::<i32>(), Some(5i32));
213     assert!(extensions.get::<i32>().is_none());
214 
215     assert_eq!(extensions.get::<bool>(), None);
216     assert_eq!(extensions.get(), Some(&MyType(10)));
217 }
218