use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use crate::handler::BoxedHandler;
use crate::request::Request;
use crate::response::Response;
type BoxFuture = Pin<Box<dyn Future<Output = Response> + Send + 'static>>;
#[doc(hidden)]
pub trait ErasedMiddleware {
fn call(&self, req: Request, next: Next) -> BoxFuture;
}
#[doc(hidden)]
pub type BoxedMiddleware = Arc<dyn ErasedMiddleware + Send + Sync + 'static>;
pub struct Next {
middleware: Arc<[BoxedMiddleware]>,
index: usize,
handler: BoxedHandler,
}
impl Next {
pub(crate) fn new(middleware: Arc<[BoxedMiddleware]>, handler: BoxedHandler) -> Self {
Self { middleware, index: 0, handler }
}
pub fn call(self, req: Request) -> Pin<Box<dyn Future<Output = Response> + Send + 'static>> {
if self.index < self.middleware.len() {
let mw = Arc::clone(&self.middleware[self.index]);
let next = Next {
middleware: self.middleware,
index: self.index + 1,
handler: self.handler,
};
mw.call(req, next)
} else {
self.handler.call(req)
}
}
}
mod private {
pub trait Sealed {}
pub trait IntoSeal {}
}
pub trait Middleware: private::Sealed + Send + Sync + 'static {
#[doc(hidden)]
fn into_boxed_middleware(self) -> BoxedMiddleware;
}
impl<F, Fut> private::Sealed for F
where
F: Fn(Request, Next) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Response> + Send + 'static,
{
}
impl<F, Fut> Middleware for F
where
F: Fn(Request, Next) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Response> + Send + 'static,
{
fn into_boxed_middleware(self) -> BoxedMiddleware {
Arc::new(FnMiddleware(self))
}
}
struct FnMiddleware<F>(F);
impl<F, Fut> ErasedMiddleware for FnMiddleware<F>
where
F: Fn(Request, Next) -> Fut + Send + Sync,
Fut: Future<Output = Response> + Send + 'static,
{
fn call(&self, req: Request, next: Next) -> BoxFuture {
Box::pin((self.0)(req, next))
}
}
pub trait IntoMiddlewares: private::IntoSeal {
#[doc(hidden)]
fn into_middlewares(self) -> Vec<BoxedMiddleware>;
}
impl private::IntoSeal for () {}
impl IntoMiddlewares for () {
fn into_middlewares(self) -> Vec<BoxedMiddleware> {
vec![]
}
}
impl<M: Middleware> private::IntoSeal for M {}
impl<M: Middleware> IntoMiddlewares for M {
fn into_middlewares(self) -> Vec<BoxedMiddleware> {
vec![self.into_boxed_middleware()]
}
}
impl<M1: Middleware, M2: Middleware> private::IntoSeal for (M1, M2) {}
impl<M1: Middleware, M2: Middleware> IntoMiddlewares for (M1, M2) {
fn into_middlewares(self) -> Vec<BoxedMiddleware> {
vec![self.0.into_boxed_middleware(), self.1.into_boxed_middleware()]
}
}
impl<M1: Middleware, M2: Middleware, M3: Middleware> private::IntoSeal for (M1, M2, M3) {}
impl<M1: Middleware, M2: Middleware, M3: Middleware> IntoMiddlewares for (M1, M2, M3) {
fn into_middlewares(self) -> Vec<BoxedMiddleware> {
vec![
self.0.into_boxed_middleware(),
self.1.into_boxed_middleware(),
self.2.into_boxed_middleware(),
]
}
}
impl<M1: Middleware, M2: Middleware, M3: Middleware, M4: Middleware> private::IntoSeal
for (M1, M2, M3, M4)
{
}
impl<M1: Middleware, M2: Middleware, M3: Middleware, M4: Middleware> IntoMiddlewares
for (M1, M2, M3, M4)
{
fn into_middlewares(self) -> Vec<BoxedMiddleware> {
vec![
self.0.into_boxed_middleware(),
self.1.into_boxed_middleware(),
self.2.into_boxed_middleware(),
self.3.into_boxed_middleware(),
]
}
}
impl<M1: Middleware, M2: Middleware, M3: Middleware, M4: Middleware, M5: Middleware>
private::IntoSeal for (M1, M2, M3, M4, M5)
{
}
impl<M1: Middleware, M2: Middleware, M3: Middleware, M4: Middleware, M5: Middleware>
IntoMiddlewares for (M1, M2, M3, M4, M5)
{
fn into_middlewares(self) -> Vec<BoxedMiddleware> {
vec![
self.0.into_boxed_middleware(),
self.1.into_boxed_middleware(),
self.2.into_boxed_middleware(),
self.3.into_boxed_middleware(),
self.4.into_boxed_middleware(),
]
}
}