nuclear 0.0.10

[WIP] a web framework for humans
Documentation
use crate::internal_prelude::*;
use crate::middleware::Middleware;
use crate::server::Server;
use crate::state;

use std::sync::Arc;

use futures::future;

pub trait Handler: Send + Sync {
    fn handle<'t, 'a>(&'t self, req: Request) -> BoxFuture<'a, Result<Response>>
    where
        't: 'a,
        Self: 'a;

    fn with_state<S>(self, state: Arc<S>) -> WithState<Self, S>
    where
        Self: Sized,
        S: Send + Sync + 'static,
    {
        WithState { h: self, s: state }
    }

    fn wrap<M>(self, middleware: M) -> Wrap<Self, M>
    where
        Self: Sized,
        M: Middleware,
    {
        Wrap {
            h: self,
            m: middleware,
        }
    }

    fn boxed(self) -> Box<dyn Handler>
    where
        Self: Sized + 'static,
    {
        Box::new(self)
    }

    fn into_server(self) -> Server
    where
        Self: Sized + 'static,
    {
        Server::new(Box::new(self))
    }
}

impl Handler for Box<dyn Handler> {
    fn handle<'t, 'a>(&'t self, req: Request) -> BoxFuture<'a, Result<Response>>
    where
        't: 'a,
        Self: 'a,
    {
        Handler::handle(&**self, req)
    }
}

pub struct WithState<H, S> {
    h: H,
    s: Arc<S>,
}

impl<H, S> Handler for WithState<H, S>
where
    H: Handler,
    S: Send + Sync + 'static,
{
    fn handle<'t, 'a>(&'t self, req: Request) -> BoxFuture<'a, Result<Response>>
    where
        't: 'a,
        Self: 'a,
    {
        let mut fut = state::enter(&self.s, || self.h.handle(req));
        Box::pin(future::poll_fn(move |cx| {
            state::enter(&self.s, || fut.as_mut().poll(cx))
        }))
    }
}

pub struct Wrap<H, M> {
    h: H,
    m: M,
}

impl<H, M> Handler for Wrap<H, M>
where
    H: Handler,
    M: Middleware,
{
    fn handle<'t, 'a>(&'t self, req: Request) -> BoxFuture<'a, Result<Response>>
    where
        't: 'a,
        Self: 'a,
    {
        self.m.handle(req, &self.h)
    }
}