task_local_extensions/
extensions.rs1use std::any::{Any, TypeId};
5use std::collections::HashMap;
6use std::fmt;
7
8#[derive(Default)]
16pub struct Extensions {
17 map: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
18}
19
20impl Extensions {
21 pub fn new() -> Self {
23 Self {
24 map: HashMap::default(),
25 }
26 }
27
28 pub fn with<T: Send + Sync + 'static>(mut self, val: T) -> Self {
39 self.insert(val);
40 self
41 }
42
43 pub fn append(&mut self, other: &mut Self) {
45 self.map.extend(other.map.drain())
46 }
47
48 pub fn insert<T: Send + Sync + 'static>(&mut self, val: T) -> Option<T> {
52 self.map
53 .insert(TypeId::of::<T>(), Box::new(val))
54 .and_then(|boxed| (boxed as Box<dyn Any>).downcast().ok().map(|boxed| *boxed))
55 }
56
57 pub fn contains<T: 'static>(&self) -> bool {
59 self.map.get(&TypeId::of::<T>()).is_some()
60 }
61
62 pub fn get<T: 'static>(&self) -> Option<&T> {
64 self.map
65 .get(&TypeId::of::<T>())
66 .and_then(|boxed| (&**boxed as &(dyn Any)).downcast_ref())
67 }
68
69 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
71 self.map
72 .get_mut(&TypeId::of::<T>())
73 .and_then(|boxed| (&mut **boxed as &mut (dyn Any)).downcast_mut())
74 }
75
76 pub fn remove<T: 'static>(&mut self) -> Option<T> {
80 self.map
81 .remove(&TypeId::of::<T>())
82 .and_then(|boxed| (boxed as Box<dyn Any>).downcast().ok().map(|boxed| *boxed))
83 }
84
85 #[inline]
87 pub fn clear(&mut self) {
88 self.map.clear();
89 }
90}
91
92impl fmt::Debug for Extensions {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 f.debug_struct("Extensions").finish()
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 #[test]
102 fn test_extensions() {
103 #[derive(Debug, PartialEq)]
104 struct MyType(i32);
105
106 let mut map = Extensions::new();
107
108 map.insert(5i32);
109 map.insert(MyType(10));
110
111 assert_eq!(map.get(), Some(&5i32));
112 assert_eq!(map.get_mut(), Some(&mut 5i32));
113
114 assert_eq!(map.remove::<i32>(), Some(5i32));
115 assert!(map.get::<i32>().is_none());
116
117 assert_eq!(map.get::<bool>(), None);
118 assert_eq!(map.get(), Some(&MyType(10)));
119 }
120}