#![allow(non_snake_case)]
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use futures_util::future::BoxFuture;
use crate::extractors::FromRequest;
use crate::responder::Responder;
use crate::types::Request;
use crate::types::Response;
pub trait Handler<T>: Send + Sync + 'static {
type Future: Future<Output = Response> + Send + 'static;
fn call(self, req: Request) -> Self::Future;
}
#[derive(Clone)]
pub struct BoxHandler {
inner: Arc<dyn Fn(Request) -> BoxFuture<'static, Response> + Send + Sync>,
}
impl BoxHandler {
pub(crate) fn new<H, T>(h: H) -> Self
where
H: Handler<T> + Clone,
{
let inner = Arc::new(move |req: Request| {
let handler = h.clone();
Box::pin(async move { handler.call(req).await }) as BoxFuture<'_, Response>
});
Self { inner }
}
pub(crate) fn call(&self, req: Request) -> BoxFuture<'_, Response> {
(self.inner)(req)
}
}
impl<F, Fut, R> Handler<()> for F
where
F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = R> + Send + 'static,
R: Responder,
{
type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
fn call(self, _req: Request) -> Self::Future {
Box::pin(async move { (self)().await.into_response() })
}
}
impl<F, Fut, R> Handler<(Request,)> for F
where
F: FnOnce(Request) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = R> + Send + 'static,
R: Responder,
{
type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
fn call(self, req: Request) -> Self::Future {
Box::pin(async move { (self)(req).await.into_response() })
}
}
trait Extract: Sized + Send {
type Error: Responder;
fn extract<'a>(
req: &'a mut Request,
) -> Pin<Box<dyn Future<Output = core::result::Result<Self, Self::Error>> + Send + 'a>>;
}
impl<T, E> Extract for T
where
T: Send,
E: Responder,
for<'a> T: FromRequest<'a, Error = E>,
{
type Error = E;
fn extract<'a>(
req: &'a mut Request,
) -> Pin<Box<dyn Future<Output = core::result::Result<Self, Self::Error>> + Send + 'a>> {
Box::pin(<T as FromRequest<'a>>::from_request(req))
}
}
macro_rules! impl_handler {
($($T:ident),+ $(,)?) => {
impl<Func, Fut, R, $($T,)*> Handler<($($T,)*)> for Func
where
Func: FnOnce($($T),*) -> Fut + Clone + Send + Sync + 'static,
Fut: Future<Output = R> + Send + 'static,
R: Responder,
$( $T: Extract + Send, )*
{
type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
fn call(self, mut req: Request) -> Self::Future {
Box::pin(async move {
$(
let $T = match <$T as Extract>::extract(&mut req).await {
Ok(value) => value,
Err(err) => {
return err.into_response();
}
};
)*
(self)($($T),*).await.into_response()
})
}
}
};
}
impl_handler!(T1);
impl_handler!(T1, T2);
impl_handler!(T1, T2, T3);
impl_handler!(T1, T2, T3, T4);
impl_handler!(T1, T2, T3, T4, T5);
impl_handler!(T1, T2, T3, T4, T5, T6);
impl_handler!(T1, T2, T3, T4, T5, T6, T7);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);