use crate::ctx::Ctx;
use crate::router::Router;
use async_trait::async_trait;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Flow {
Continue,
Stop,
}
#[async_trait]
pub trait Middleware: Send + Sync + 'static {
async fn handle(&self, ctx: Arc<Ctx>, next: Next<'_>) -> Flow;
}
pub struct Next<'a> {
pub(crate) remaining: &'a [Arc<dyn Middleware>],
pub(crate) terminal: &'a Router,
}
impl<'a> Next<'a> {
pub fn run(self, ctx: Arc<Ctx>) -> Pin<Box<dyn Future<Output = Flow> + Send + 'a>> {
Box::pin(async move {
match self.remaining.split_first() {
Some((mw, rest)) => {
let next = Next { remaining: rest, terminal: self.terminal };
mw.handle(ctx, next).await
}
None => {
self.terminal.run_handlers(ctx).await;
Flow::Continue
}
}
})
}
}