use crate::{FromRequest, FromRequestParts, IntoResponse, Result};
use axol_http::{Body, request::RequestPartsRef, response::Response};
use futures::Future;
#[async_trait::async_trait]
pub trait Handler: Send + Sync + 'static {
async fn call<'a>(&self, request_parts: RequestPartsRef<'a>, body: Body) -> Result<Response>;
}
#[async_trait::async_trait]
pub trait HandlerExpansion<G>: Send + Sync + 'static {
async fn call<'a>(&self, request_parts: RequestPartsRef<'a>, body: Body) -> Result<Response>;
}
#[async_trait::async_trait]
impl<G: 'static> Handler for Box<dyn HandlerExpansion<G>> {
async fn call<'a>(&self, request_parts: RequestPartsRef<'a>, body: Body) -> Result<Response> {
(**self).call(request_parts, body).await
}
}
#[async_trait::async_trait]
impl<F, Fut, Res> HandlerExpansion<()> for F
where
F: Fn() -> Fut + Send + Sync + 'static,
Fut: Future<Output = Res> + Send,
Res: IntoResponse,
{
async fn call<'a>(&self, _request_parts: RequestPartsRef<'a>, _body: Body) -> Result<Response> {
self().await.into_response()
}
}
macro_rules! impl_handler {
(
[$($ty:ident),*], $last:ident
) => {
#[allow(non_snake_case)]
#[async_trait::async_trait]
impl<F, Fut, Res, M, $($ty,)* $last> HandlerExpansion<(M, ($($ty,)* $last,), Fut, Res)> for F
where for<'a> F: Fn($($ty,)* $last,) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Res> + Send + 'static,
Res: IntoResponse,
$( for<'a> $ty: FromRequestParts<'a> + Send, )*
for<'a> $last: FromRequest<'a, M> + Send,
{
async fn call<'a>(&self, request_parts: RequestPartsRef<'a>, body: Body) -> Result<Response> {
$(
let $ty = $ty::from_request_parts(request_parts).await?;
)*
let $last = $last::from_request(request_parts, body).await?;
let res = self($($ty,)* $last,).await;
res.into_response()
}
}
};
}
all_the_tuples!(impl_handler);