Skip to main content

caelix_core/
events.rs

1use crate::{BoxFuture, Container, Injectable, Module, ModuleMetadata, Result};
2use std::{
3    any::{Any, TypeId},
4    collections::HashMap,
5    marker::PhantomData,
6    sync::{Arc, RwLock},
7};
8
9#[diagnostic::on_unimplemented(
10    message = "`{Self}` is not an event handler for `{E}`",
11    label = "missing `impl EventHandler<{E}> for {Self}`",
12    note = "add `impl EventHandler<{E}> for {Self}` or use the correct event type in `.event_handler_for::<Event, Handler>()`"
13)]
14pub trait EventHandler<E>: Send + Sync + 'static {
15    fn handle(&self, event: E) -> BoxFuture<'_, Result<()>>;
16}
17
18#[diagnostic::on_unimplemented(
19    message = "`{Self}` cannot be registered with `.event_handler::<{Self}>()` yet",
20    label = "missing `impl RegisterableEventHandler for {Self}`",
21    note = "add `impl RegisterableEventHandler for {Self} {{ type Event = YourEvent; }}` or use `.event_handler_for::<YourEvent, {Self}>()`"
22)]
23pub trait RegisterableEventHandler: Injectable {
24    type Event: Clone + Send + Sync + 'static;
25
26    fn register_into(handler: Arc<Self>, bus: &EventBus)
27    where
28        Self: Sized + EventHandler<Self::Event>,
29    {
30        bus.register::<Self::Event, Self>(handler);
31    }
32}
33
34trait ErasedHandler: Send + Sync {
35    fn handle_erased(&self, event: &dyn Any) -> BoxFuture<'_, Result<()>>;
36}
37
38struct TypedHandler<E, H> {
39    handler: Arc<H>,
40    _marker: PhantomData<E>,
41}
42
43impl<E, H> ErasedHandler for TypedHandler<E, H>
44where
45    E: Clone + Send + Sync + 'static,
46    H: EventHandler<E>,
47{
48    fn handle_erased(&self, event: &dyn Any) -> BoxFuture<'_, Result<()>> {
49        let event = event
50            .downcast_ref::<E>()
51            .expect("event type mismatch")
52            .clone();
53        let handler = self.handler.clone();
54
55        Box::pin(async move { handler.handle(event).await })
56    }
57}
58
59pub struct EventBus {
60    handlers: RwLock<HashMap<TypeId, Vec<Arc<dyn ErasedHandler>>>>,
61}
62
63impl EventBus {
64    pub fn new() -> Self {
65        Self {
66            handlers: RwLock::new(HashMap::new()),
67        }
68    }
69
70    pub fn register<E, H>(&self, handler: Arc<H>)
71    where
72        E: Clone + Send + Sync + 'static,
73        H: EventHandler<E>,
74    {
75        let wrapped = Arc::new(TypedHandler::<E, H> {
76            handler,
77            _marker: PhantomData,
78        });
79
80        self.handlers
81            .write()
82            .expect("event handler registry lock poisoned")
83            .entry(TypeId::of::<E>())
84            .or_default()
85            .push(wrapped);
86    }
87
88    pub async fn emit<E>(&self, event: E) -> Result<()>
89    where
90        E: Clone + Send + Sync + 'static,
91    {
92        let handlers = self
93            .handlers
94            .read()
95            .expect("event handler registry lock poisoned")
96            .get(&TypeId::of::<E>())
97            .cloned();
98
99        if let Some(handlers) = handlers {
100            for handler in handlers {
101                handler.handle_erased(&event).await?;
102            }
103        }
104
105        Ok(())
106    }
107
108    pub fn handler_count<E>(&self) -> usize
109    where
110        E: Clone + Send + Sync + 'static,
111    {
112        self.handlers
113            .read()
114            .expect("event handler registry lock poisoned")
115            .get(&TypeId::of::<E>())
116            .map_or(0, Vec::len)
117    }
118}
119
120impl Default for EventBus {
121    fn default() -> Self {
122        Self::new()
123    }
124}
125
126impl Injectable for EventBus {
127    fn create(_container: &Container) -> BoxFuture<'_, Self> {
128        Box::pin(async { Self::new() })
129    }
130}
131
132pub struct EventModule;
133
134impl Module for EventModule {
135    fn register() -> ModuleMetadata {
136        ModuleMetadata::new().provider::<EventBus>()
137    }
138}
139
140pub struct EventHandlerDef {
141    type_id: TypeId,
142    type_name: &'static str,
143    register_fn: Box<dyn Fn(&Container) + Send + Sync>,
144}
145
146impl EventHandlerDef {
147    pub(crate) fn of<H>() -> Self
148    where
149        H: RegisterableEventHandler + EventHandler<H::Event>,
150    {
151        Self {
152            type_id: TypeId::of::<H>(),
153            type_name: std::any::type_name::<H>(),
154            register_fn: Box::new(|container| {
155                let handler = container.resolve::<H>();
156                let bus = container.resolve::<EventBus>();
157                H::register_into(handler, &bus);
158            }),
159        }
160    }
161
162    pub(crate) fn for_event<E, H>() -> Self
163    where
164        E: Clone + Send + Sync + 'static,
165        H: Injectable + EventHandler<E>,
166    {
167        Self {
168            type_id: TypeId::of::<H>(),
169            type_name: std::any::type_name::<H>(),
170            register_fn: Box::new(|container| {
171                let handler = container.resolve::<H>();
172                let bus = container.resolve::<EventBus>();
173                bus.register::<E, H>(handler);
174            }),
175        }
176    }
177
178    pub(crate) fn try_assert_registered(&self, container: &Container) -> Result<()> {
179        if container.contains_type_id(self.type_id) {
180            return Ok(());
181        }
182
183        Err(crate::exception::startup_error(format!(
184            "missing event handler provider at startup: {} was declared by module metadata but was not registered as a provider",
185            self.type_name
186        )))
187    }
188
189    pub(crate) fn register(&self, container: &Container) {
190        (self.register_fn)(container);
191    }
192}