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}