mod_events/listener.rs
1//! Event listener traits and implementations
2
3use crate::{Event, Priority};
4
5/// Trait for synchronous event listeners
6///
7/// Implement this trait to create reusable event listeners.
8/// For simple cases, you can use closures with the dispatcher's
9/// `subscribe` or `on` methods instead.
10///
11/// # Example
12///
13/// ```rust
14/// use mod_events::{Event, EventListener, Priority};
15///
16/// #[derive(Debug, Clone)]
17/// struct UserRegistered {
18/// user_id: u64,
19/// email: String,
20/// }
21///
22/// impl Event for UserRegistered {
23/// fn as_any(&self) -> &dyn std::any::Any {
24/// self
25/// }
26/// }
27///
28/// struct EmailNotifier;
29///
30/// impl EventListener<UserRegistered> for EmailNotifier {
31/// fn handle(&self, event: &UserRegistered) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
32/// // Send email logic here
33/// println!("Sending email to {}", event.email);
34/// Ok(())
35/// }
36///
37/// fn priority(&self) -> Priority {
38/// Priority::High
39/// }
40/// }
41/// ```
42pub trait EventListener<T: Event>: Send + Sync {
43 /// Handle the event
44 ///
45 /// This method is called when the event is dispatched.
46 /// Return `Ok(())` on success or an error on failure.
47 fn handle(&self, event: &T) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
48
49 /// Get the priority of this listener
50 ///
51 /// Higher priority listeners are executed first.
52 /// Default is `Priority::Normal`.
53 fn priority(&self) -> Priority {
54 Priority::Normal
55 }
56}
57
58/// Internal listener wrapper for type erasure
59type ListenerHandler =
60 dyn Fn(&dyn Event) -> Result<(), Box<dyn std::error::Error + Send + Sync>> + Send + Sync;
61
62pub(crate) struct ListenerWrapper {
63 pub(crate) handler: Box<ListenerHandler>,
64 pub(crate) priority: Priority,
65 pub(crate) id: usize,
66}
67
68impl std::fmt::Debug for ListenerWrapper {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 f.debug_struct("ListenerWrapper")
71 .field("priority", &self.priority)
72 .field("id", &self.id)
73 .field("handler", &"<function>")
74 .finish()
75 }
76}
77
78impl ListenerWrapper {
79 pub(crate) fn new<T, F>(listener: F, priority: Priority, id: usize) -> Self
80 where
81 T: Event + 'static,
82 F: Fn(&T) -> Result<(), Box<dyn std::error::Error + Send + Sync>> + Send + Sync + 'static,
83 {
84 Self {
85 handler: Box::new(move |event: &dyn Event| {
86 if let Some(concrete_event) = event.as_any().downcast_ref::<T>() {
87 listener(concrete_event)
88 } else {
89 Ok(())
90 }
91 }),
92 priority,
93 id,
94 }
95 }
96}