orbit/events/
dispatcher.rs

1//! Event dispatcher for typed event handling
2//!
3//! This module provides a type-safe event dispatch system with thread-safety
4//! and proper error handling.
5
6use std::sync::{Arc, Mutex};
7
8use super::Event;
9
10/// Handler trait for processing events
11pub trait Handler<E>: Send + Sync {
12    /// Handle an event
13    fn handle(&self, event: &E) -> Result<(), String>;
14}
15
16/// Implement Handler for Fn(&E)
17impl<E, F> Handler<E> for F
18where
19    F: Fn(&E) -> Result<(), String> + Send + Sync,
20{
21    fn handle(&self, event: &E) -> Result<(), String> {
22        self(event)
23    }
24}
25
26/// Thread-safe event dispatcher for a specific event type
27#[derive(Clone)]
28pub struct Dispatcher<E: Event> {
29    /// List of event handlers protected by a mutex
30    handlers: Arc<Mutex<Vec<Box<dyn Handler<E>>>>>,
31}
32
33impl<E: Event> Default for Dispatcher<E> {
34    fn default() -> Self {
35        Self::new()
36    }
37}
38
39impl<E: Event> Dispatcher<E> {
40    /// Create a new event dispatcher
41    pub fn new() -> Self {
42        Self {
43            handlers: Arc::new(Mutex::new(Vec::new())),
44        }
45    }
46
47    /// Add a new event handler
48    pub fn add_handler<H>(&mut self, handler: H) -> Result<(), String>
49    where
50        H: Handler<E> + 'static,
51    {
52        let mut handlers = self
53            .handlers
54            .lock()
55            .map_err(|e| format!("Failed to lock handlers: {e}"))?;
56
57        handlers.push(Box::new(handler));
58        Ok(())
59    }
60
61    /// Add a handler function directly
62    pub fn on<F>(&mut self, f: F) -> Result<(), String>
63    where
64        F: Fn(&E) -> Result<(), String> + Send + Sync + 'static,
65    {
66        self.add_handler(f)
67    }
68
69    /// Dispatch an event to all handlers
70    pub fn dispatch(&self, event: &E) -> Result<(), String> {
71        let handlers = self
72            .handlers
73            .lock()
74            .map_err(|e| format!("Failed to lock handlers: {e}"))?;
75
76        let mut errors = Vec::new();
77
78        for handler in handlers.iter() {
79            if let Err(e) = handler.handle(event) {
80                errors.push(e);
81            }
82        }
83
84        if errors.is_empty() {
85            Ok(())
86        } else {
87            Err(errors.join(", "))
88        }
89    }
90
91    /// Remove all handlers
92    pub fn clear(&mut self) -> Result<(), String> {
93        let mut handlers = self
94            .handlers
95            .lock()
96            .map_err(|e| format!("Failed to lock handlers: {e}"))?;
97
98        handlers.clear();
99        Ok(())
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    use std::sync::atomic::{AtomicBool, Ordering};
107
108    #[derive(Clone)]
109    struct TestEvent {
110        data: String,
111    }
112
113    // TestEvent automatically implements Event through the blanket implementation
114
115    #[test]
116    fn test_dispatcher() {
117        let mut dispatcher = Dispatcher::<TestEvent>::new();
118        let called = Arc::new(AtomicBool::new(false));
119        let called_clone = called.clone();
120
121        dispatcher
122            .on(move |event: &TestEvent| {
123                called_clone.store(true, Ordering::SeqCst);
124                assert_eq!(event.data, "test");
125                Ok(())
126            })
127            .unwrap();
128
129        dispatcher
130            .dispatch(&TestEvent {
131                data: "test".to_string(),
132            })
133            .unwrap();
134
135        assert!(called.load(Ordering::SeqCst));
136    }
137}