use std::{
any::{Any, TypeId},
collections::HashMap,
sync::Arc,
};
use funcext::FuncExt;
use futures_util::future::join_all;
use tokio::sync::RwLock;
#[async_trait::async_trait]
pub trait Handler: Send + Sync {
type E;
async fn handle(&self, e: Arc<Self::E>);
}
#[async_trait::async_trait]
trait ErasedHandler: Send + Sync {
async fn handle_erased(&self, e: Arc<dyn Any + Send + Sync>);
}
struct HandlerWrapper<E>(Arc<dyn Handler<E = E> + Send + Sync>);
#[async_trait::async_trait]
impl<E: Any + Send + Sync + 'static> ErasedHandler for HandlerWrapper<E> {
async fn handle_erased(&self, e: Arc<dyn Any + Send + Sync>) {
if let Ok(event) = e.downcast::<E>() {
self.0.handle(event).await;
}
}
}
#[derive(Default)]
pub struct EventDispatcher(RwLock<HashMap<TypeId, Vec<Arc<dyn ErasedHandler>>>>);
impl EventDispatcher {
pub fn new() -> Self {
Self(RwLock::new(HashMap::new()))
}
pub async fn register<E: Send + Sync + 'static>(
&self,
handler: Arc<dyn Handler<E = E> + Send + Sync>,
) {
let mut collection = self.0.write().await;
collection
.entry(TypeId::of::<E>())
.or_default()
.push(Arc::new(HandlerWrapper(handler)));
}
pub async fn emit<E: Send + Sync + 'static>(&self, event: E) {
self.emit_arc(Arc::new(event)).await;
}
pub async fn emit_arc<E: Send + Sync + 'static>(&self, event: Arc<E>) {
let collection = self.0.read().await;
let Some(handlers) = collection.get(&TypeId::of::<E>()) else {
return;
};
let event: Arc<dyn Any + Send + Sync> = event;
handlers
.iter()
.map(|h| h.handle_erased(event.clone()))
.R(join_all)
.await;
}
}