use crate::{Event, ListenerError, Priority};
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
pub type AsyncEventResult<'a> =
Pin<Box<dyn Future<Output = Result<(), ListenerError>> + Send + 'a>>;
pub trait AsyncEventListener<T: Event>: Send + Sync {
fn handle<'a>(&'a self, event: &'a T) -> AsyncEventResult<'a>;
fn priority(&self) -> Priority {
Priority::Normal
}
}
type AsyncEventHandler = dyn for<'a> Fn(&'a dyn Event) -> AsyncEventResult<'a> + Send + Sync;
pub(crate) struct AsyncListenerWrapper {
pub(crate) handler: Arc<AsyncEventHandler>,
pub(crate) priority: Priority,
pub(crate) id: usize,
}
impl std::fmt::Debug for AsyncListenerWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AsyncListenerWrapper")
.field("priority", &self.priority)
.field("id", &self.id)
.field("handler", &"<async_function>")
.finish()
}
}
impl AsyncListenerWrapper {
pub(crate) fn new<T, F, Fut>(listener: F, priority: Priority, id: usize) -> Self
where
T: Event + 'static,
F: Fn(&T) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<(), ListenerError>> + Send + 'static,
{
Self {
handler: Arc::new(move |event: &dyn Event| {
if let Some(concrete_event) = event.as_any().downcast_ref::<T>() {
Box::pin(listener(concrete_event))
} else {
Box::pin(async { Ok(()) })
}
}),
priority,
id,
}
}
}