axol 0.2.0

Axol Web Framework
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);