puzz_http/
extensions.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::{BuildHasherDefault, Hasher};
5
6type AnyMap = HashMap<TypeId, Box<dyn Any>, BuildHasherDefault<IdHasher>>;
7
8// 使用`TypeId`作为键时,不需要进行散列。
9#[derive(Default)]
10struct IdHasher(u64);
11
12impl Hasher for IdHasher {
13    fn write(&mut self, _: &[u8]) {
14        unreachable!("TypeId calls write_u64");
15    }
16
17    #[inline]
18    fn write_u64(&mut self, id: u64) {
19        self.0 = id;
20    }
21
22    #[inline]
23    fn finish(&self) -> u64 {
24        self.0
25    }
26}
27
28/// 请求和响应的扩展组件。
29///
30/// 请求和响应可以使用扩展来存储额外的数据。
31#[derive(Default)]
32pub struct Extensions {
33    // 如果从不使用扩展,则无需携带空的`HashMap`,并且这只占用一个字长。
34    map: Option<Box<AnyMap>>,
35}
36
37impl Extensions {
38    /// 创建一个空的扩展。
39    #[inline]
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    /// 向扩展中插入一个类型。
45    ///
46    /// 如果这种类型已经存在,将替换并返回先前插入的值。
47    ///
48    /// # 例子
49    ///
50    /// ```
51    /// use puzz_http::Extensions;
52    ///
53    /// let mut ext = Extensions::new();
54    ///
55    /// assert!(ext.insert(5i32).is_none());
56    /// assert!(ext.insert(4u8).is_none());
57    /// assert_eq!(ext.insert(9i32), Some(5i32));
58    /// ```
59    pub fn insert<T: 'static>(&mut self, val: T) -> Option<T> {
60        self.map
61            .get_or_insert_with(|| Box::new(HashMap::default()))
62            .insert(TypeId::of::<T>(), Box::new(val))
63            .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
64    }
65
66    /// 获取先前插入扩展的类型的引用。
67    ///
68    /// # 例子
69    ///
70    /// ```
71    /// use puzz_http::Extensions;
72    ///
73    /// let mut ext = Extensions::new();
74    /// assert!(ext.get::<i32>().is_none());
75    ///
76    /// ext.insert(5i32);
77    /// assert_eq!(ext.get::<i32>(), Some(&5i32));
78    /// ```
79    pub fn get<T: 'static>(&self) -> Option<&T> {
80        self.map
81            .as_ref()
82            .and_then(|map| map.get(&TypeId::of::<T>()))
83            .and_then(|boxed| boxed.downcast_ref())
84    }
85
86    /// 获取先前插入扩展的类型的可变引用。
87    ///
88    /// # 例子
89    ///
90    /// ```
91    /// use puzz_http::Extensions;
92    ///
93    /// let mut ext = Extensions::new();
94    ///
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    pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
101        self.map
102            .as_mut()
103            .and_then(|map| map.get_mut(&TypeId::of::<T>()))
104            .and_then(|boxed| boxed.downcast_mut())
105    }
106
107    /// 从扩展中删除一个类型。
108    ///
109    /// 如果这种类型存在,将删除并返回此类型。
110    ///
111    /// # 例子
112    ///
113    /// ```
114    /// use puzz_http::Extensions;
115    ///
116    /// let mut ext = Extensions::new();
117    ///
118    /// ext.insert(5i32);
119    ///
120    /// assert_eq!(ext.remove::<i32>(), Some(5i32));
121    /// assert!(ext.get::<i32>().is_none());
122    /// ```
123    pub fn remove<T: 'static>(&mut self) -> Option<T> {
124        self.map
125            .as_mut()
126            .and_then(|map| map.remove(&TypeId::of::<T>()))
127            .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
128    }
129
130    /// 清空扩展中的所有类型。
131    ///
132    /// # 例子
133    ///
134    /// ```
135    /// use puzz_http::Extensions;
136    ///
137    /// let mut ext = Extensions::new();
138    ///
139    /// ext.insert(5i32);
140    /// ext.clear();
141    ///
142    /// assert!(ext.get::<i32>().is_none());
143    /// ```
144    #[inline]
145    pub fn clear(&mut self) {
146        if let Some(ref mut map) = self.map {
147            map.clear();
148        }
149    }
150
151    /// 检查扩展是否为空。
152    ///
153    /// # 例子
154    ///
155    /// ```
156    /// use puzz_http::Extensions;
157    ///
158    /// let mut ext = Extensions::new();
159    /// assert!(ext.is_empty());
160    ///
161    /// ext.insert(5i32);
162    /// assert!(!ext.is_empty());
163    /// ```
164    #[inline]
165    pub fn is_empty(&self) -> bool {
166        self.map.as_ref().map_or(true, |map| map.is_empty())
167    }
168
169    /// 获取扩展中已插入类型的数量。
170    ///
171    /// # 例子
172    ///
173    /// ```
174    /// use puzz_http::Extensions;
175    ///
176    /// let mut ext = Extensions::new();
177    /// assert_eq!(ext.len(), 0);
178    ///
179    /// ext.insert(5i32);
180    /// assert_eq!(ext.len(), 1);
181    /// ```
182    #[inline]
183    pub fn len(&self) -> usize {
184        self.map.as_ref().map_or(0, |map| map.len())
185    }
186}
187
188impl fmt::Debug for Extensions {
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190        f.debug_struct("Extensions").finish()
191    }
192}