use std::future::Future;
use std::sync::Arc;
use tracing::warn;
use crate::actor::{ArcEvent, ErasedHandler, ListenerMode};
use crate::error::HandlerResult;
use crate::types::Event;
pub trait EventHandler<E: Event + Clone>: Send + Sync + 'static {
fn handle(&self, event: &E) -> impl Future<Output = HandlerResult> + Send;
}
pub trait SyncEventHandler<E: Event>: Send + Sync + 'static {
fn handle(&self, event: &E) -> HandlerResult;
}
pub struct AsyncMode;
pub struct SyncMode;
pub(crate) struct RegisteredHandler {
pub erased: ErasedHandler,
pub mode: ListenerMode,
}
#[allow(private_interfaces)]
pub trait IntoHandler<E: Event, Mode> {
#[doc(hidden)]
fn into_handler(self) -> RegisteredHandler;
}
#[allow(private_interfaces)]
impl<E, H> IntoHandler<E, AsyncMode> for H
where
E: Event + Clone,
H: EventHandler<E>,
{
fn into_handler(self) -> RegisteredHandler {
let handler = Arc::new(self);
let erased: ErasedHandler = Arc::new(move |any: ArcEvent| {
let handler = Arc::clone(&handler);
if let Some(event) = any.as_ref().downcast_ref::<E>() {
let event = event.clone();
Box::pin(async move { handler.handle(&event).await })
} else {
warn!(expected = std::any::type_name::<E>(), "handler.downcast_failed");
Box::pin(async { Ok(()) })
}
});
RegisteredHandler {
erased,
mode: ListenerMode::Async,
}
}
}
#[allow(private_interfaces)]
impl<E, H> IntoHandler<E, SyncMode> for H
where
E: Event,
H: SyncEventHandler<E>,
{
fn into_handler(self) -> RegisteredHandler {
let handler = Arc::new(self);
let erased: ErasedHandler = Arc::new(move |any: ArcEvent| {
let result = if let Some(event) = any.as_ref().downcast_ref::<E>() {
handler.handle(event)
} else {
warn!(expected = std::any::type_name::<E>(), "handler.downcast_failed");
Ok(())
};
Box::pin(async move { result })
});
RegisteredHandler {
erased,
mode: ListenerMode::Sync,
}
}
}