use crate::Context;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
#[async_trait::async_trait]
pub trait Event: Debug + Sync {
async fn call(&self, ctx: &mut Context) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait EventOnce: Debug + Sync {
async fn call(self: Box<Self>, ctx: &mut Context) -> anyhow::Result<()>;
}
#[async_trait::async_trait]
pub trait EventExt<T>: Sync {
async fn call(&self, ctx: &mut Context, input: &mut T) -> anyhow::Result<()>;
}
pub struct EventExtLayer<T, E> {
inner: E,
_marker: PhantomData<T>,
}
impl<T, E> Debug for EventExtLayer<T, E> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventExtLayer").finish_non_exhaustive()
}
}
impl<T, E> EventExtLayer<T, E> {
pub fn new(event: E) -> Self {
Self {
inner: event,
_marker: PhantomData,
}
}
}
#[async_trait::async_trait]
impl<T, E> Event for EventExtLayer<T, E>
where
E: EventExt<T> + Send + 'static,
T: Debug + Sync + Send + 'static,
{
async fn call(&self, ctx: &mut Context) -> anyhow::Result<()> {
let mut input = if let Some(input) = ctx.try_into_inner::<T>() {
input
} else {
return Err(anyhow::anyhow!("input is nil or is not T"));
};
let result = self.inner.call(ctx, &mut input).await;
if ctx.is_empty_input() {
ctx.set_input(input);
}
result
}
}
#[async_trait::async_trait]
pub trait EventOnceExt<T>: Sync {
async fn call(self, ctx: &mut Context, input: &mut T) -> anyhow::Result<()>;
}
pub struct EventOnceExtLayer<T, E> {
inner: E,
_marker: PhantomData<T>,
}
impl<T, E> Debug for EventOnceExtLayer<T, E> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventOnceExtLayer").finish_non_exhaustive()
}
}
impl<T, E> EventOnceExtLayer<T, E> {
pub fn new(event: E) -> Self {
Self {
inner: event,
_marker: PhantomData,
}
}
}
#[async_trait::async_trait]
impl<T, E> EventOnce for EventOnceExtLayer<T, E>
where
E: EventOnceExt<T> + Sync + Send + 'static,
T: Debug + Sync + Send + 'static,
{
async fn call(self: Box<Self>, ctx: &mut Context) -> anyhow::Result<()> {
let mut input = if let Some(input) = ctx.try_into_inner::<T>() {
input
} else {
return Err(anyhow::anyhow!("input is nil or is not T"));
};
let result = self.inner.call(ctx, &mut input).await;
if ctx.is_empty_input() {
ctx.set_input(input);
}
result
}
}
#[async_trait::async_trait]
impl<T, I, F> EventExt<I> for T
where
T: Fn(&mut Context, &mut I) -> F + Sync + Send + 'static,
I: Sync + Send + 'static,
F: Future<Output = Result<(), anyhow::Error>> + Send,
{
async fn call(&self, ctx: &mut Context, input: &mut I) -> anyhow::Result<()> {
(self)(ctx, input).await
}
}
#[async_trait::async_trait]
impl<T, I, F> EventOnceExt<I> for T
where
T: FnOnce(&mut Context, &mut I) -> F + Sync + Send + 'static,
I: Sync + Send + 'static,
F: Future<Output = Result<(), anyhow::Error>> + Send,
{
async fn call(self, ctx: &mut Context, input: &mut I) -> anyhow::Result<()> {
(self)(ctx, input).await
}
}