use std::fmt::Debug;
use std::future::Future;
use std::sync::Arc;
use async_trait::async_trait;
use crate::middleware::{Next};
use crate::{Middleware};
#[async_trait]
pub trait Endpoint: Send + Sync {
async fn call(&self, ctx: &mut crate::Context) -> crate::Result;
}
pub(crate) type DynEndpoint = dyn Endpoint;
impl Debug for DynEndpoint {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "dyn Endpoint<{:?}>", std::any::type_name::<Self>())
}
}
#[async_trait::async_trait]
impl<F> Endpoint for F
where
F: for<'a1> Fn1<&'a1 mut crate::Context> + Sync + Send,
for<'a1> <F as Fn1<&'a1 mut crate::Context>>::Output: Future<Output = crate::Result> + Send,
{
async fn call(&self, ctx: &mut crate::Context) -> crate::Result {
self(ctx).await
}
}
trait Fn1<Arg1>: Fn(Arg1) -> <Self as Fn1<Arg1>>::Output {
type Output;
}
impl<F: Fn(Arg1) -> O, Arg1, O> Fn1<Arg1> for F {
type Output = O;
}
pub(crate) struct MiddlewareEndpoint {
endpoint: Arc<dyn Endpoint>,
middleware: Arc<Vec<Arc<dyn Middleware>>>,
}
impl Clone for MiddlewareEndpoint {
fn clone(&self) -> Self {
Self {
endpoint: self.endpoint.clone(),
middleware: self.middleware.clone(),
}
}
}
impl std::fmt::Debug for MiddlewareEndpoint {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
fmt,
"MiddlewareEndpoint (length: {})",
self.middleware.len(),
)
}
}
impl MiddlewareEndpoint
{
pub(crate) fn wrap_with_middleware(
ep: impl Endpoint + 'static,
middleware: Vec<Arc<dyn Middleware>>,
) -> Arc<dyn Endpoint + Send + Sync> {
if middleware.is_empty() {
Arc::new(ep)
} else {
Arc::new(Self {
endpoint: Arc::new(ep),
middleware: Arc::new(middleware),
})
}
}
}
#[async_trait]
impl Endpoint for MiddlewareEndpoint {
async fn call(&self, ctx: &mut crate::Context) -> crate::Result {
let next = Next::new(self.endpoint.clone(), self.middleware.clone());
next.run(ctx).await
}
}
#[async_trait]
impl Endpoint for Box<dyn Endpoint> {
async fn call(&self, ctx: &mut crate::Context) -> crate::Result {
self.as_ref().call(ctx).await
}
}