Skip to main content

silent/configs/
mod.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::fmt;
4use std::hash::{BuildHasherDefault, Hasher};
5use std::sync::Arc;
6
7type AnyMap = HashMap<TypeId, Arc<dyn Any + Send + Sync>, BuildHasherDefault<IdHasher>>;
8
9// With TypeIds as keys, there's no need to hash them. They are already hashes
10// themselves, coming from the compiler. The IdHasher just holds the u64 of
11// the TypeId, and then returns it, instead of doing any bit fiddling.
12#[derive(Default)]
13struct IdHasher(u64);
14
15impl Hasher for IdHasher {
16    #[inline]
17    fn finish(&self) -> u64 {
18        self.0
19    }
20
21    fn write(&mut self, _: &[u8]) {
22        unreachable!("TypeId calls write_u64");
23    }
24
25    #[inline]
26    fn write_u64(&mut self, id: u64) {
27        self.0 = id;
28    }
29}
30
31/// 类型安全的键值存储容器。
32///
33/// `State` 用于按类型存储和检索值,是 `State` 和 `Configs` 的底层实现。
34/// 可被 `Request` 和 `Response` 用来存储从底层协议派生的额外数据。
35#[derive(Default, Clone)]
36pub struct State {
37    // If extensions are never used, no need to carry around an empty HashMap.
38    // That's 3 words. Instead, this is only 1 word.
39    map: Option<Box<AnyMap>>,
40}
41
42/// `Configs` 是 `State` 的类型别名,保持向后兼容。
43///
44/// **已弃用**:请使用 `State<T>` 提取器代替 `Configs<T>` 提取器。
45/// `Configs` 将在 v2.18.0 中移除。
46#[deprecated(
47    since = "2.16.0",
48    note = "请使用 State<T> 提取器代替,Configs 将在 v2.18.0 移除"
49)]
50pub type Configs = State;
51
52impl State {
53    /// Create an empty `State`.
54    #[inline]
55    pub fn new() -> State {
56        State { map: None }
57    }
58
59    /// Insert a type into this `State`.
60    ///
61    /// If an extension of this type already existed, it will
62    /// be returned.
63    ///
64    /// # Example
65    ///
66    /// ```
67    /// # use silent::State;
68    /// let mut cfg = State::new();
69    /// assert!(cfg.insert(5i32).is_none());
70    /// assert!(cfg.insert(4u8).is_none());
71    /// assert_eq!(cfg.insert(9i32), Some(5i32));
72    /// ```
73    pub fn insert<T: Send + Sync + Clone + 'static>(&mut self, val: T) -> Option<T> {
74        self.map
75            .get_or_insert_with(Box::default)
76            .insert(TypeId::of::<T>(), Arc::new(val))
77            .and_then(|boxed| (boxed as Arc<dyn Any + 'static>).downcast_ref().cloned())
78    }
79
80    /// Get a reference to a type previously inserted on this `State`.
81    ///
82    /// # Example
83    ///
84    /// ```
85    /// # use silent::State;
86    /// let mut cfg = State::new();
87    /// assert!(cfg.get::<i32>().is_none());
88    /// cfg.insert(5i32);
89    ///
90    /// assert_eq!(cfg.get::<i32>(), Some(&5i32));
91    /// ```
92    pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
93        self.map
94            .as_ref()
95            .and_then(|map| map.get(&TypeId::of::<T>()))
96            .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
97    }
98
99    /// Remove a type from this `State`.
100    ///
101    /// If aa extension of this type existed, it will be returned.
102    ///
103    /// # Example
104    ///
105    /// ```
106    /// # use silent::State;
107    /// let mut cfg = State::new();
108    /// cfg.insert(5i32);
109    /// assert_eq!(cfg.remove::<i32>(), Some(5i32));
110    /// assert!(cfg.get::<i32>().is_none());
111    /// ```
112    pub fn remove<T: Send + Sync + Clone + 'static>(&mut self) -> Option<T> {
113        self.map
114            .as_mut()
115            .and_then(|map| map.remove(&TypeId::of::<T>()))
116            .and_then(|boxed| (boxed as Arc<dyn Any + 'static>).downcast_ref().cloned())
117    }
118
119    /// Clear the `State` of all inserted extensions.
120    ///
121    /// # Example
122    ///
123    /// ```
124    /// # use silent::State;
125    /// let mut cfg = State::new();
126    /// cfg.insert(5i32);
127    /// cfg.clear();
128    ///
129    /// assert!(cfg.get::<i32>().is_none());
130    /// ```
131    #[inline]
132    pub fn clear(&mut self) {
133        if let Some(ref mut map) = self.map {
134            map.clear();
135        }
136    }
137
138    /// Check whether the extension set is empty or not.
139    ///
140    /// # Example
141    ///
142    /// ```
143    /// # use silent::State;
144    /// let mut cfg = State::new();
145    /// assert!(cfg.is_empty());
146    /// cfg.insert(5i32);
147    /// assert!(!cfg.is_empty());
148    /// ```
149    #[inline]
150    pub fn is_empty(&self) -> bool {
151        self.map.as_ref().is_none_or(|map| map.is_empty())
152    }
153
154    /// Get the numer of extensions available.
155    ///
156    /// # Example
157    ///
158    /// ```
159    /// # use silent::State;
160    /// let mut cfg = State::new();
161    /// assert_eq!(cfg.len(), 0);
162    /// cfg.insert(5i32);
163    /// assert_eq!(cfg.len(), 1);
164    /// ```
165    #[inline]
166    pub fn len(&self) -> usize {
167        self.map.as_ref().map_or(0, |map| map.len())
168    }
169
170    /// 将另一个 State 的内容合并进来(浅拷贝 Arc 值)
171    #[inline]
172    pub fn extend_from(&mut self, other: &State) {
173        if let Some(other_map) = other.map.as_ref() {
174            let dst = self.map.get_or_insert_with(Box::default);
175            for (k, v) in other_map.iter() {
176                dst.insert(*k, v.clone());
177            }
178        }
179    }
180}
181
182impl fmt::Debug for State {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        f.debug_struct("State").finish()
185    }
186}
187
188#[cfg(test)]
189mod tests {
190    use super::*;
191    use std::sync::RwLock;
192    use tracing::{error, info};
193
194    #[test]
195    fn test_type_map() {
196        #[derive(Debug, PartialEq, Clone)]
197        struct MyType(i32);
198
199        let mut configs = State::new();
200
201        configs.insert(5i32);
202        configs.insert(MyType(10));
203
204        assert_eq!(configs.get(), Some(&5i32));
205        // assert_eq!(configs.get_mut(), Some(&mut 5i32));
206
207        assert_eq!(configs.remove::<i32>(), Some(5i32));
208        assert!(configs.get::<i32>().is_none());
209
210        assert_eq!(configs.get::<bool>(), None);
211        assert_eq!(configs.get(), Some(&MyType(10)));
212
213        #[derive(Debug, PartialEq, Clone)]
214        struct MyStringType(String);
215
216        configs.insert(MyStringType("Hello".to_string()));
217
218        assert_eq!(
219            configs.get::<MyStringType>(),
220            Some(&MyStringType("Hello".to_string()))
221        );
222
223        use std::thread;
224        for i in 0..100 {
225            let configs = configs.clone();
226            thread::spawn(move || {
227                if i % 5 == 0 {
228                    // let mut configs = configs.clone();
229                    let configs = configs.clone();
230                    match configs.get::<MyStringType>() {
231                        Some(my_type) => {
232                            // my_type.0 = i.to_string();
233                            info!("Ok: i:{}, v:{}", i, my_type.0)
234                        }
235                        _ => {
236                            info!("Err: i:{}", i)
237                        }
238                    }
239                } else {
240                    match configs.get::<MyStringType>() {
241                        Some(my_type) => {
242                            info!("Ok: i:{}, v:{}", i, my_type.0)
243                        }
244                        _ => {
245                            info!("Err: i:{}", i)
246                        }
247                    }
248                }
249            });
250        }
251    }
252
253    #[test]
254    fn test_type_map_mut_ref() {
255        let mut configs = State::default();
256        #[derive(Debug, PartialEq, Clone)]
257        struct MyStringType(String);
258
259        configs.insert(Arc::new(RwLock::new(MyStringType("Hello".to_string()))));
260        assert_eq!(
261            configs
262                .get::<Arc<RwLock<MyStringType>>>()
263                .cloned()
264                .unwrap()
265                .read()
266                .unwrap()
267                .0
268                .clone(),
269            "Hello"
270        );
271
272        use std::thread;
273        for i in 0..100 {
274            let configs = configs.clone();
275            thread::spawn(move || {
276                if i % 5 == 0 {
277                    let configs = configs.clone();
278                    match configs.get::<Arc<RwLock<MyStringType>>>().cloned() {
279                        Some(my_type) => match my_type.write() {
280                            Ok(mut my_type) => {
281                                my_type.0 = i.to_string();
282                                info!("Ok: i:{}, v:{}", i, my_type.0)
283                            }
284                            _ => {
285                                error!("Rwlock Lock Err: i:{}", i)
286                            }
287                        },
288                        _ => {
289                            error!("Get Err: i:{}", i)
290                        }
291                    }
292                } else {
293                    match configs.get::<Arc<RwLock<MyStringType>>>() {
294                        Some(my_type) => match my_type.read() {
295                            Ok(my_type) => {
296                                info!("Ok: i:{}, v:{}", i, my_type.0)
297                            }
298                            _ => {
299                                error!("Rwlock Read Err: i:{}", i)
300                            }
301                        },
302                        _ => {
303                            error!("Err: i:{}", i)
304                        }
305                    }
306                }
307            });
308        }
309    }
310}