athene 2.0.4

A simple and lightweight rust web framework based on hyper
Documentation
use crate::{request::Request, responder::Responder, response::Builder};
use async_trait::async_trait;
use std::future::Future;

pub type ControllerMethod<C> = (
    Option<&'static str>,
    &'static str,
    &'static str,
    Box<dyn ControllerHandler<C> + Send + Sync>,
);

pub trait Controller {
    const BASE_PATH: &'static str;

    fn method(&self) -> Vec<ControllerMethod<Self>>
    where
        Self: Sized;
}

#[async_trait]
pub trait ControllerHandler<C> {
    async fn handle(&self, controller: &'static C, req: Request) -> Builder;
}

#[async_trait]
impl<C, F, Fut, R> ControllerHandler<C> for F
where
    C: 'static + Sync,
    R: Responder + 'static + Send,
    Fut: Future<Output = R> + Send + 'static,
    F: Fn(&'static C, Request) -> Fut + Sync,
{
    #[inline]
    async fn handle(&self, controller: &'static C, req: Request) -> Builder {
        let builder = Builder::new();
        self(controller, req).await.response(builder)
    }
}

macro_rules! method {
    ($($(#[$m:meta])* $v:vis fn $n:ident = $method:expr;)+) => {
        $(
            $(#[$m])* $v fn $n<H>(self,path: &'static str,handler: H) -> Self
            where
                H: ControllerHandler<C> + Send + Sync + 'static,
            {
                self.add(path,$method,handler)
            }
        )+
    };
}

#[derive(Default)]
pub struct ControllerBuilder<C: Controller> {
    handlers: Vec<ControllerMethod<C>>,
}

impl<C: Controller> ControllerBuilder<C> {
    #[inline]
    pub fn new() -> Self {
        Self {
            handlers: Default::default(),
        }
    }

    #[inline]
    fn add<H>(mut self, path: &'static str, method: &'static str, handler: H) -> Self
    where
        H: ControllerHandler<C> + Send + Sync + 'static,
    {
        self.handlers.push((None, method, path, Box::new(handler)));
        self
    }

    #[inline]
    pub fn add_with_name<H>(
        mut self,
        handler_name: &'static str,
        path: &'static str,
        method: &'static str,
        handler: H,
    ) -> Self
    where
        H: 'static + ControllerHandler<C> + Send + Sync,
    {
        self.handlers
            .push((Some(handler_name), method, path, Box::new(handler)));
        self
    }

    method![
        #[inline]
        pub fn get = "GET";
        #[inline]
        pub fn post = "POST";
        #[inline]
        pub fn options = "OPTIONS";
        #[inline]
        pub fn put = "PUT";
        #[inline]
        pub fn delete = "DELETE";
        #[inline]
        pub fn head = "HEAD";
        #[inline]
        pub fn trace = "TRACE";
        #[inline]
        pub fn connect = "CONNECT";
        #[inline]
        pub fn patch = "PATCH";
    ];

    #[inline]
    pub fn build(self) -> Vec<ControllerMethod<C>> {
        self.handlers
    }
}