use std::{fmt::Debug, sync::Arc};
type HandlerLink<T, E> = Arc<Vec<Arc<Box<dyn ChannelHandler_<T, E>>>>>;
pub struct ProceedingJoinPoint<T, E>
where
E: std::error::Error,
{
index: usize,
link: HandlerLink<T, E>,
pub context: T,
}
impl<T, E> ProceedingJoinPoint<T, E>
where
E: std::error::Error,
{
pub fn new(link: HandlerLink<T, E>, context: T) -> Self {
Self {
index: 0,
link,
context,
}
}
pub fn into_context(self) -> T {
self.context
}
pub async fn proceed(mut self) -> Result<T, E> {
match self.link.get(self.index) {
Some(filter) => {
self.index += 1;
filter.clone().call(self).await
}
None => Ok(self.into_context()),
}
}
}
pub type BoxFuture<'a, T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + 'a>>;
pub trait ChannelHandler_<T, E>: Send + Sync + Debug
where
E: std::error::Error,
{
fn call<'a>(&'a self, join_point: ProceedingJoinPoint<T, E>) -> BoxFuture<'a, Result<T, E>>;
}
#[allow(async_fn_in_trait)]
pub trait ChannelHandler<T, E>
where
E: std::error::Error,
{
async fn aroud(&self, join_point: ProceedingJoinPoint<T, E>) -> Result<T, E>;
}
#[derive(Debug)]
pub enum HandlerInvoker<T, E> {
ChannelHandler(Box<dyn ChannelHandler_<T, E>>),
}
#[derive(Debug)]
pub struct Handler<T, E> {
pub id: String,
pub handler_invoker: HandlerInvoker<T, E>,
}
pub trait HandlerLoad {
fn load<T, E>(self) -> Handler<T, E>;
}