use std::any::Any;
use std::any::TypeId;
use std::sync::Arc;
use scc::HashMap as SccHashMap;
#[derive(Default)]
pub struct RouterState {
inner: SccHashMap<TypeId, Arc<dyn Any + Send + Sync>>,
}
impl std::fmt::Debug for RouterState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RouterState").finish_non_exhaustive()
}
}
impl RouterState {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn insert<T: Send + Sync + 'static>(&self, value: T) {
let _ = self.inner.insert_sync(TypeId::of::<T>(), Arc::new(value));
}
pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
self
.inner
.get_sync(&TypeId::of::<T>())
.map(|v| v.clone())
.and_then(|v| v.downcast::<T>().ok())
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn len(&self) -> usize {
self.inner.len()
}
}
#[derive(Debug, Clone)]
pub struct MatchedPath(pub String);
impl MatchedPath {
#[inline]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl<'a> crate::extractors::FromRequest<'a> for MatchedPath {
type Error = MatchedPathMissing;
fn from_request(
req: &'a mut crate::types::Request,
) -> impl core::future::Future<Output = core::result::Result<Self, Self::Error>> + Send + 'a {
futures_util::future::ready(
req
.extensions()
.get::<MatchedPath>()
.cloned()
.ok_or(MatchedPathMissing),
)
}
}
impl<'a> crate::extractors::FromRequestParts<'a> for MatchedPath {
type Error = MatchedPathMissing;
fn from_request_parts(
parts: &'a mut http::request::Parts,
) -> impl core::future::Future<Output = core::result::Result<Self, Self::Error>> + Send + 'a {
futures_util::future::ready(
parts
.extensions
.get::<MatchedPath>()
.cloned()
.ok_or(MatchedPathMissing),
)
}
}
#[derive(Debug)]
pub struct MatchedPathMissing;
impl crate::responder::Responder for MatchedPathMissing {
fn into_response(self) -> crate::types::Response {
let mut res = crate::types::Response::new(crate::body::TakoBody::from(
"matched path is unavailable on this request",
));
*res.status_mut() = http::StatusCode::INTERNAL_SERVER_ERROR;
res
}
}