use std::fmt::Debug;
use std::sync::Arc;
use crate::endpoint::DynEndpoint;
use async_trait::async_trait;
use std::future::Future;
#[async_trait]
pub trait Middleware: Send + Sync {
async fn handle(&self, ctx: &mut crate::Context, next: Next) -> crate::Result;
fn name(&self) -> &str {
std::any::type_name::<Self>()
}
}
impl Debug for dyn Middleware {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"dyn Middleware<{:?}>",
std::any::type_name::<Self>(),
)
}
}
#[async_trait::async_trait]
impl<F> Middleware for F
where
F: for<'arg1> Fn1<&'arg1 mut crate::Context, Next> + Sync + Send,
for<'arg1> <F as Fn1<&'arg1 mut crate::Context, Next>>::Output: Future<Output = crate::Result> + Send,
{
async fn handle(&self, ctx: &mut crate::Context, next: Next) -> crate::Result {
self(ctx, next).await
}
}
trait Fn1<Arg1, Arg2>: Fn(Arg1, Arg2) -> <Self as Fn1<Arg1, Arg2>>::Output {
type Output;
}
impl<F: Fn(Arg1, Arg2) -> O, Arg1, Arg2, O> Fn1<Arg1, Arg2> for F {
type Output = O;
}
#[derive(Debug)]
pub struct Next {
endpoint: Arc<DynEndpoint>,
middleware: Arc<Vec<Arc<dyn Middleware>>>,
current_index: usize,
}
impl Next {
pub fn new(
endpoint: Arc<DynEndpoint>,
middleware: Arc<Vec<Arc<dyn Middleware>>>,
) -> Next {
Next {
endpoint,
middleware,
current_index: 0,
}
}
pub async fn run(mut self, ctx: &mut crate::Context) -> crate::Result {
let current_index = self.current_index; self.current_index += 1;
match self.middleware.get(current_index) {
Some(current) => current.clone().handle(ctx, self).await,
None => self.endpoint.call(ctx).await,
}
}
}