1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3use std::fmt::{self, Debug, Formatter};
4
5#[derive(Default)]
38pub struct Depot {
39 map: HashMap<String, Box<dyn Any + Send + Sync>>,
40}
41
42#[inline]
43fn type_key<T: 'static>() -> String {
44 format!("{:?}", TypeId::of::<T>())
45}
46
47impl Depot {
48 #[inline]
53 #[must_use]
54 pub fn new() -> Self {
55 Self {
56 map: HashMap::new(),
57 }
58 }
59
60 #[inline]
62 #[must_use]
63 pub fn inner(&self) -> &HashMap<String, Box<dyn Any + Send + Sync>> {
64 &self.map
65 }
66
67 #[inline]
72 #[must_use]
73 pub fn with_capacity(capacity: usize) -> Self {
74 Self {
75 map: HashMap::with_capacity(capacity),
76 }
77 }
78 #[inline]
80 #[must_use]
81 pub fn capacity(&self) -> usize {
82 self.map.capacity()
83 }
84
85 #[inline]
87 pub fn inject<V: Any + Send + Sync>(&mut self, value: V) -> &mut Self {
88 self.map.insert(type_key::<V>(), Box::new(value));
89 self
90 }
91
92 #[inline]
98 pub fn obtain<T: Any + Send + Sync>(&self) -> Result<&T, Option<&Box<dyn Any + Send + Sync>>> {
99 self.get(&type_key::<T>())
100 }
101
102 #[inline]
108 pub fn obtain_mut<T: Any + Send + Sync>(
109 &mut self,
110 ) -> Result<&mut T, Option<&mut Box<dyn Any + Send + Sync>>> {
111 self.get_mut(&type_key::<T>())
112 }
113
114 #[inline]
116 pub fn insert<K, V>(&mut self, key: K, value: V) -> &mut Self
117 where
118 K: Into<String>,
119 V: Any + Send + Sync,
120 {
121 self.map.insert(key.into(), Box::new(value));
122 self
123 }
124
125 #[inline]
127 #[must_use]
128 pub fn contains_key(&self, key: &str) -> bool {
129 self.map.contains_key(key)
130 }
131 #[inline]
135 #[must_use]
136 pub fn contains<T: Any + Send + Sync>(&self) -> bool {
137 self.map.contains_key(&type_key::<T>())
138 }
139
140 #[inline]
146 pub fn get<V: Any + Send + Sync>(
147 &self,
148 key: &str,
149 ) -> Result<&V, Option<&Box<dyn Any + Send + Sync>>> {
150 if let Some(value) = self.map.get(key) {
151 value.downcast_ref::<V>().ok_or(Some(value))
152 } else {
153 Err(None)
154 }
155 }
156
157 pub fn get_mut<V: Any + Send + Sync>(
163 &mut self,
164 key: &str,
165 ) -> Result<&mut V, Option<&mut Box<dyn Any + Send + Sync>>> {
166 if let Some(value) = self.map.get_mut(key) {
167 if value.downcast_mut::<V>().is_some() {
168 Ok(value
169 .downcast_mut::<V>()
170 .expect("downcast_mut should not be failed"))
171 } else {
172 Err(Some(value))
173 }
174 } else {
175 Err(None)
176 }
177 }
178
179 #[inline]
182 pub fn remove<V: Any + Send + Sync>(
183 &mut self,
184 key: &str,
185 ) -> Result<V, Option<Box<dyn Any + Send + Sync>>> {
186 if let Some(value) = self.map.remove(key) {
187 value.downcast::<V>().map(|b| *b).map_err(Some)
188 } else {
189 Err(None)
190 }
191 }
192
193 #[inline]
195 pub fn delete(&mut self, key: &str) -> bool {
196 self.map.remove(key).is_some()
197 }
198
199 #[inline]
201 pub fn scrape<T: Any + Send + Sync>(
202 &mut self,
203 ) -> Result<T, Option<Box<dyn Any + Send + Sync>>> {
204 self.remove(&type_key::<T>())
205 }
206}
207
208impl Debug for Depot {
209 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
210 f.debug_struct("Depot")
211 .field("keys", &self.map.keys())
212 .finish()
213 }
214}
215
216#[cfg(test)]
217mod test {
218 use super::*;
219 use crate::prelude::*;
220 use crate::test::{ResponseExt, TestClient};
221
222 #[test]
223 fn test_depot() {
224 let mut depot = Depot::with_capacity(6);
225 assert!(depot.capacity() >= 6);
226
227 depot.insert("one", "ONE".to_owned());
228 assert!(depot.contains_key("one"));
229
230 assert_eq!(depot.get::<String>("one").unwrap(), &"ONE".to_owned());
231 assert_eq!(
232 depot.get_mut::<String>("one").unwrap(),
233 &mut "ONE".to_owned()
234 );
235 }
236
237 #[tokio::test]
238 async fn test_middleware_use_depot() {
239 #[handler]
240 async fn set_user(
241 req: &mut Request,
242 depot: &mut Depot,
243 res: &mut Response,
244 ctrl: &mut FlowCtrl,
245 ) {
246 depot.insert("user", "client");
247 ctrl.call_next(req, depot, res).await;
248 }
249 #[handler]
250 async fn hello(depot: &mut Depot) -> String {
251 format!(
252 "Hello {}",
253 depot.get::<&str>("user").copied().unwrap_or_default()
254 )
255 }
256 let router = Router::new().hoop(set_user).goal(hello);
257 let service = Service::new(router);
258
259 let content = TestClient::get("http://127.0.0.1:8698")
260 .send(&service)
261 .await
262 .take_string()
263 .await
264 .unwrap();
265 assert_eq!(content, "Hello client");
266 }
267}