mincat-core 0.1.0

Core types and traits for mincat
Documentation
use std::{collections::VecDeque, fmt::Debug, future::Future, marker::PhantomData};

use mincat_macro::repeat_macro_max_generics_param;

use crate::{
    middleware::Middleware,
    next::Next,
    request::{FromRequest, FromRequestParts, Request},
    response::{IntoResponse, Response},
};

#[derive(Clone)]
pub struct Handler {
    pub func: Box<dyn HandlerFunc>,
    pub middleware: Option<VecDeque<Box<dyn Middleware>>>,
}

impl Debug for Handler {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut middleware_len = 0;
        if let Some(middleware) = &self.middleware {
            middleware_len = middleware.len();
        }

        f.debug_struct("Handler")
            .field("func", &"func")
            .field("middleware", &middleware_len)
            .finish()
    }
}

impl Handler {
    pub fn middleware<T>(&mut self, middleware: T) -> Self
    where
        T: Into<Box<dyn Middleware>>,
    {
        self.middleware
            .get_or_insert(VecDeque::new())
            .push_back(middleware.into());

        self.clone()
    }

    pub async fn exectue(self, request: Request) -> Response {
        Next::new(self).run(request).await
    }
}

#[async_trait::async_trait]
pub trait HandlerFunc: Send + Sync {
    async fn call(self: Box<Self>, request: Request) -> Response;

    fn clone_box(&self) -> Box<dyn HandlerFunc>;
}

impl Clone for Box<dyn HandlerFunc> {
    fn clone(&self) -> Self {
        self.clone_box()
    }
}

#[async_trait::async_trait]
pub trait HandlerFuncParam<Param>: Send {
    async fn call(self, request: Request) -> Response;
}

#[derive(Clone)]
pub struct FuncParamHandler<Func, Param>
where
    Func: HandlerFuncParam<Param>,
{
    func: Func,
    _mark: PhantomData<Param>,
}

impl<Func, Param> From<Func> for FuncParamHandler<Func, Param>
where
    Func: HandlerFuncParam<Param>,
{
    fn from(value: Func) -> Self {
        Self {
            func: value,
            _mark: PhantomData,
        }
    }
}

impl<Func, Param> From<FuncParamHandler<Func, Param>> for Handler
where
    Func: HandlerFuncParam<Param> + Clone + Sync + 'static,
    Param: Send + Sync + 'static,
{
    fn from(value: FuncParamHandler<Func, Param>) -> Self {
        Handler {
            func: Box::new(value),
            middleware: None,
        }
    }
}

#[async_trait::async_trait]
impl<Func, Param> HandlerFunc for FuncParamHandler<Func, Param>
where
    Func: HandlerFuncParam<Param> + Clone + Sync + 'static,
    Param: Send + Sync + 'static,
{
    async fn call(self: Box<Self>, request: Request) -> Response {
        self.func.call(request).await
    }

    fn clone_box(&self) -> Box<dyn HandlerFunc> {
        Box::new(Self {
            func: self.func.clone(),
            _mark: PhantomData,
        })
    }
}

#[async_trait::async_trait]
impl<Func, Fut, Res> HandlerFuncParam<((),)> for Func
where
    Func: FnOnce() -> Fut,
    Func: Clone + Send + Sync + 'static,
    Fut: Future<Output = Res> + Send,
    Res: IntoResponse,
{
    async fn call(self, _: Request) -> Response {
        self().await.into_response()
    }
}

macro_rules! handle_func_param {
    ([$($param: ident),*], $lastparam:ident) => {
        #[allow(non_snake_case)]
        #[async_trait::async_trait]
        impl<Func, Fut, Res, $($param,)* $lastparam> HandlerFuncParam<($($param,)* $lastparam,)> for Func
        where
            Func: FnOnce($($param,)* $lastparam,) -> Fut,
            Func: Clone + Send + Sync + 'static,
            Fut: Future<Output = Res> + Send,
            Res: IntoResponse,
            $($param: FromRequestParts + Send,)*
            $lastparam: FromRequest + Send
        {
            async fn call(self, request: Request) -> Response {
                #[allow(unused_mut)]
                let (mut parts, body) = request.into_parts();

                $(
                    let $param = match $param::from_request_parts(&mut parts).await {
                        Ok(v) => v,
                        Err(e) => return e.into_response(),
                    };
                )*

                let request = Request::from_parts(parts, body);

                let $lastparam = match $lastparam::from_request(request).await {
                    Ok(v) => v,
                    Err(e) => return e.into_response(),
                };

                let res = self($($param,)* $lastparam,).await;

                res.into_response()
            }

        }
    }
}

macro_rules! handle_func_param_pre {
    ($($param: ident),*) => {
        handle_func_param!([$($param),*], T);
    }
}

repeat_macro_max_generics_param!(handle_func_param_pre, 0, 17, P);