Coverage Report

Created: 2025-07-11 06:41

/rust/registry/src/index.crates.io-6f17d22bba15001f/http-1.3.1/src/extensions.rs
Line
Count
Source (jump to first uncovered line)
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 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)]
12
struct IdHasher(u64);
13
14
impl Hasher for IdHasher {
15
0
    fn write(&mut self, _: &[u8]) {
16
0
        unreachable!("TypeId calls write_u64");
17
    }
18
19
    #[inline]
20
0
    fn write_u64(&mut self, id: u64) {
21
0
        self.0 = id;
22
0
    }
23
24
    #[inline]
25
0
    fn finish(&self) -> u64 {
26
0
        self.0
27
0
    }
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(Clone, 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]
44
0
    pub fn new() -> Extensions {
45
0
        Extensions { map: None }
46
0
    }
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 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
    /// ```
62
0
    pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
63
0
        self.map
64
0
            .get_or_insert_with(Box::default)
65
0
            .insert(TypeId::of::<T>(), Box::new(val))
66
0
            .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
67
0
    }
68
69
    /// Get a reference to a type previously inserted on this `Extensions`.
70
    ///
71
    /// # Example
72
    ///
73
    /// ```
74
    /// # use http::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
0
    pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
82
0
        self.map
83
0
            .as_ref()
84
0
            .and_then(|map| map.get(&TypeId::of::<T>()))
85
0
            .and_then(|boxed| (**boxed).as_any().downcast_ref())
86
0
    }
87
88
    /// Get a mutable reference to a type previously inserted on this `Extensions`.
89
    ///
90
    /// # Example
91
    ///
92
    /// ```
93
    /// # use http::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
0
    pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
101
0
        self.map
102
0
            .as_mut()
103
0
            .and_then(|map| map.get_mut(&TypeId::of::<T>()))
104
0
            .and_then(|boxed| (**boxed).as_any_mut().downcast_mut())
105
0
    }
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 http::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
0
    pub fn get_or_insert<T: Clone + Send + Sync + 'static>(&mut self, value: T) -> &mut T {
120
0
        self.get_or_insert_with(|| value)
121
0
    }
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 http::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
0
    pub fn get_or_insert_with<T: Clone + Send + Sync + 'static, F: FnOnce() -> T>(
136
0
        &mut self,
137
0
        f: F,
138
0
    ) -> &mut T {
139
0
        let out = self
140
0
            .map
141
0
            .get_or_insert_with(Box::default)
142
0
            .entry(TypeId::of::<T>())
143
0
            .or_insert_with(|| Box::new(f()));
144
0
        (**out).as_any_mut().downcast_mut().unwrap()
145
0
    }
146
147
    /// Get a mutable reference to a type, inserting the type's default value if not already present
148
    /// on this `Extensions`.
149
    ///
150
    /// # Example
151
    ///
152
    /// ```
153
    /// # use http::Extensions;
154
    /// let mut ext = Extensions::new();
155
    /// *ext.get_or_insert_default::<i32>() += 2;
156
    ///
157
    /// assert_eq!(*ext.get::<i32>().unwrap(), 2);
158
    /// ```
159
0
    pub fn get_or_insert_default<T: Default + Clone + Send + Sync + 'static>(&mut self) -> &mut T {
160
0
        self.get_or_insert_with(T::default)
161
0
    }
162
163
    /// Remove a type from this `Extensions`.
164
    ///
165
    /// If a extension of this type existed, it will be returned.
166
    ///
167
    /// # Example
168
    ///
169
    /// ```
170
    /// # use http::Extensions;
171
    /// let mut ext = Extensions::new();
172
    /// ext.insert(5i32);
173
    /// assert_eq!(ext.remove::<i32>(), Some(5i32));
174
    /// assert!(ext.get::<i32>().is_none());
175
    /// ```
176
0
    pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T> {
177
0
        self.map
178
0
            .as_mut()
179
0
            .and_then(|map| map.remove(&TypeId::of::<T>()))
180
0
            .and_then(|boxed| boxed.into_any().downcast().ok().map(|boxed| *boxed))
181
0
    }
182
183
    /// Clear the `Extensions` of all inserted extensions.
184
    ///
185
    /// # Example
186
    ///
187
    /// ```
188
    /// # use http::Extensions;
189
    /// let mut ext = Extensions::new();
190
    /// ext.insert(5i32);
191
    /// ext.clear();
192
    ///
193
    /// assert!(ext.get::<i32>().is_none());
194
    /// ```
195
    #[inline]
196
0
    pub fn clear(&mut self) {
197
0
        if let Some(ref mut map) = self.map {
198
0
            map.clear();
199
0
        }
200
0
    }
201
202
    /// Check whether the extension set is empty or not.
203
    ///
204
    /// # Example
205
    ///
206
    /// ```
207
    /// # use http::Extensions;
208
    /// let mut ext = Extensions::new();
209
    /// assert!(ext.is_empty());
210
    /// ext.insert(5i32);
211
    /// assert!(!ext.is_empty());
212
    /// ```
213
    #[inline]
214
0
    pub fn is_empty(&self) -> bool {
215
0
        self.map.as_ref().map_or(true, |map| map.is_empty())
216
0
    }
217
218
    /// Get the number of extensions available.
219
    ///
220
    /// # Example
221
    ///
222
    /// ```
223
    /// # use http::Extensions;
224
    /// let mut ext = Extensions::new();
225
    /// assert_eq!(ext.len(), 0);
226
    /// ext.insert(5i32);
227
    /// assert_eq!(ext.len(), 1);
228
    /// ```
229
    #[inline]
230
0
    pub fn len(&self) -> usize {
231
0
        self.map.as_ref().map_or(0, |map| map.len())
232
0
    }
233
234
    /// Extends `self` with another `Extensions`.
235
    ///
236
    /// If an instance of a specific type exists in both, the one in `self` is overwritten with the
237
    /// one from `other`.
238
    ///
239
    /// # Example
240
    ///
241
    /// ```
242
    /// # use http::Extensions;
243
    /// let mut ext_a = Extensions::new();
244
    /// ext_a.insert(8u8);
245
    /// ext_a.insert(16u16);
246
    ///
247
    /// let mut ext_b = Extensions::new();
248
    /// ext_b.insert(4u8);
249
    /// ext_b.insert("hello");
250
    ///
251
    /// ext_a.extend(ext_b);
252
    /// assert_eq!(ext_a.len(), 3);
253
    /// assert_eq!(ext_a.get::<u8>(), Some(&4u8));
254
    /// assert_eq!(ext_a.get::<u16>(), Some(&16u16));
255
    /// assert_eq!(ext_a.get::<&'static str>().copied(), Some("hello"));
256
    /// ```
257
0
    pub fn extend(&mut self, other: Self) {
258
0
        if let Some(other) = other.map {
259
0
            if let Some(map) = &mut self.map {
260
0
                map.extend(*other);
261
0
            } else {
262
0
                self.map = Some(other);
263
0
            }
264
0
        }
265
0
    }
266
}
267
268
impl fmt::Debug for Extensions {
269
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270
0
        f.debug_struct("Extensions").finish()
271
0
    }
272
}
273
274
trait AnyClone: Any {
275
    fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync>;
276
    fn as_any(&self) -> &dyn Any;
277
    fn as_any_mut(&mut self) -> &mut dyn Any;
278
    fn into_any(self: Box<Self>) -> Box<dyn Any>;
279
}
280
281
impl<T: Clone + Send + Sync + 'static> AnyClone for T {
282
0
    fn clone_box(&self) -> Box<dyn AnyClone + Send + Sync> {
283
0
        Box::new(self.clone())
284
0
    }
285
286
0
    fn as_any(&self) -> &dyn Any {
287
0
        self
288
0
    }
289
290
0
    fn as_any_mut(&mut self) -> &mut dyn Any {
291
0
        self
292
0
    }
293
294
0
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
295
0
        self
296
0
    }
297
}
298
299
impl Clone for Box<dyn AnyClone + Send + Sync> {
300
0
    fn clone(&self) -> Self {
301
0
        (**self).clone_box()
302
0
    }
303
}
304
305
#[test]
306
fn test_extensions() {
307
    #[derive(Clone, Debug, PartialEq)]
308
    struct MyType(i32);
309
310
    let mut extensions = Extensions::new();
311
312
    extensions.insert(5i32);
313
    extensions.insert(MyType(10));
314
315
    assert_eq!(extensions.get(), Some(&5i32));
316
    assert_eq!(extensions.get_mut(), Some(&mut 5i32));
317
318
    let ext2 = extensions.clone();
319
320
    assert_eq!(extensions.remove::<i32>(), Some(5i32));
321
    assert!(extensions.get::<i32>().is_none());
322
323
    // clone still has it
324
    assert_eq!(ext2.get(), Some(&5i32));
325
    assert_eq!(ext2.get(), Some(&MyType(10)));
326
327
    assert_eq!(extensions.get::<bool>(), None);
328
    assert_eq!(extensions.get(), Some(&MyType(10)));
329
}