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     /// Extends `self` with another `Extensions`.
193     ///
194     /// If an instance of a specific type exists in both, the one in `self` is overwritten with the
195     /// one from `other`.
196     ///
197     /// # Example
198     ///
199     /// ```
200     /// # use http::Extensions;
201     /// let mut ext_a = Extensions::new();
202     /// ext_a.insert(8u8);
203     /// ext_a.insert(16u16);
204     ///
205     /// let mut ext_b = Extensions::new();
206     /// ext_b.insert(4u8);
207     /// ext_b.insert("hello");
208     ///
209     /// ext_a.extend(ext_b);
210     /// assert_eq!(ext_a.len(), 3);
211     /// assert_eq!(ext_a.get::<u8>(), Some(&4u8));
212     /// assert_eq!(ext_a.get::<u16>(), Some(&16u16));
213     /// assert_eq!(ext_a.get::<&'static str>().copied(), Some("hello"));
214     /// ```
extend(&mut self, other: Self)215     pub fn extend(&mut self, other: Self) {
216         if let Some(other) = other.map {
217             if let Some(map) = &mut self.map {
218                 map.extend(*other);
219             } else {
220                 self.map = Some(other);
221             }
222         }
223     }
224 }
225 
226 impl fmt::Debug for Extensions {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result227     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228         f.debug_struct("Extensions").finish()
229     }
230 }
231 
232 #[test]
test_extensions()233 fn test_extensions() {
234     #[derive(Debug, PartialEq)]
235     struct MyType(i32);
236 
237     let mut extensions = Extensions::new();
238 
239     extensions.insert(5i32);
240     extensions.insert(MyType(10));
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 }
251