#![allow(unsafe_code)]
use log::trace;
use std::panic::RefUnwindSafe;
use std::pin::Pin;
use crate::handler::HandlerFuture;
use crate::middleware::{Middleware, NewMiddleware};
use crate::state::{request_id, State};
#[doc(hidden)]
pub unsafe trait NewMiddlewareChain: RefUnwindSafe + Sized {
type Instance: MiddlewareChain;
fn construct(&self) -> anyhow::Result<Self::Instance>;
}
unsafe impl<T, U> NewMiddlewareChain for (T, U)
where
T: NewMiddleware,
T::Instance: Send + 'static,
U: NewMiddlewareChain,
{
type Instance = (T::Instance, U::Instance);
fn construct(&self) -> anyhow::Result<Self::Instance> {
trace!(" adding middleware instance to pipeline");
let (ref nm, ref tail) = *self;
Ok((nm.new_middleware()?, tail.construct()?))
}
}
unsafe impl NewMiddlewareChain for () {
type Instance = ();
fn construct(&self) -> anyhow::Result<Self::Instance> {
trace!(" completed middleware pipeline construction");
Ok(())
}
}
#[doc(hidden)]
pub unsafe trait MiddlewareChain: Sized {
fn call<F>(self, state: State, f: F) -> Pin<Box<HandlerFuture>>
where
F: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static;
}
unsafe impl MiddlewareChain for () {
fn call<F>(self, state: State, f: F) -> Pin<Box<HandlerFuture>>
where
F: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
{
trace!("pipeline complete, invoking handler");
f(state)
}
}
unsafe impl<T, U> MiddlewareChain for (T, U)
where
T: Middleware + Send + 'static,
U: MiddlewareChain,
{
fn call<F>(self, state: State, f: F) -> Pin<Box<HandlerFuture>>
where
F: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
{
let (m, p) = self;
trace!("[{}] executing middleware", request_id(&state));
p.call(state, move |state| m.call(state, f))
}
}