tako_rs_core/
router_state.rs1use std::any::Any;
15use std::any::TypeId;
16use std::sync::Arc;
17
18use scc::HashMap as SccHashMap;
19
20#[derive(Default)]
22pub struct RouterState {
23 inner: SccHashMap<TypeId, Arc<dyn Any + Send + Sync>>,
24}
25
26impl std::fmt::Debug for RouterState {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 f.debug_struct("RouterState").finish_non_exhaustive()
29 }
30}
31
32impl RouterState {
33 #[must_use]
35 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn insert<T: Send + Sync + 'static>(&self, value: T) {
41 let _ = self.inner.insert_sync(TypeId::of::<T>(), Arc::new(value));
42 }
43
44 pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
46 self
47 .inner
48 .get_sync(&TypeId::of::<T>())
49 .map(|v| v.clone())
50 .and_then(|v| v.downcast::<T>().ok())
51 }
52
53 pub fn is_empty(&self) -> bool {
55 self.inner.is_empty()
56 }
57
58 pub fn len(&self) -> usize {
60 self.inner.len()
61 }
62}
63
64#[derive(Debug, Clone)]
77pub struct MatchedPath(pub String);
78
79impl MatchedPath {
80 #[inline]
82 pub fn as_str(&self) -> &str {
83 &self.0
84 }
85}
86
87impl<'a> crate::extractors::FromRequest<'a> for MatchedPath {
88 type Error = MatchedPathMissing;
89
90 fn from_request(
91 req: &'a mut crate::types::Request,
92 ) -> impl core::future::Future<Output = core::result::Result<Self, Self::Error>> + Send + 'a {
93 futures_util::future::ready(
94 req
95 .extensions()
96 .get::<MatchedPath>()
97 .cloned()
98 .ok_or(MatchedPathMissing),
99 )
100 }
101}
102
103impl<'a> crate::extractors::FromRequestParts<'a> for MatchedPath {
104 type Error = MatchedPathMissing;
105
106 fn from_request_parts(
107 parts: &'a mut http::request::Parts,
108 ) -> impl core::future::Future<Output = core::result::Result<Self, Self::Error>> + Send + 'a {
109 futures_util::future::ready(
110 parts
111 .extensions
112 .get::<MatchedPath>()
113 .cloned()
114 .ok_or(MatchedPathMissing),
115 )
116 }
117}
118
119#[derive(Debug)]
121pub struct MatchedPathMissing;
122
123impl crate::responder::Responder for MatchedPathMissing {
124 fn into_response(self) -> crate::types::Response {
125 let mut res = crate::types::Response::new(crate::body::TakoBody::from(
126 "matched path is unavailable on this request",
127 ));
128 *res.status_mut() = http::StatusCode::INTERNAL_SERVER_ERROR;
129 res
130 }
131}