Skip to main content

robinpath_modules/modules/
event_mod.rs

1use robinpath::{RobinPath, Value};
2use std::collections::HashMap;
3use std::sync::{Arc, Mutex};
4
5#[derive(Clone)]
6struct EventListener {
7    handler_id: String,
8    once: bool,
9}
10
11pub fn register(rp: &mut RobinPath) {
12    let state: Arc<Mutex<HashMap<String, Vec<EventListener>>>> =
13        Arc::new(Mutex::new(HashMap::new()));
14
15    // event.on(name, handlerId) -> registers listener
16    let s = state.clone();
17    rp.register_builtin("event.on", move |args, _| {
18        let name = args.first().map(|v| v.to_display_string()).unwrap_or_default();
19        let handler_id = args.get(1).map(|v| v.to_display_string()).unwrap_or_default();
20        let mut events = s.lock().unwrap();
21        let listeners = events.entry(name).or_default();
22        listeners.push(EventListener {
23            handler_id: handler_id.clone(),
24            once: false,
25        });
26        Ok(Value::String(handler_id))
27    });
28
29    // event.off(name, handlerId) -> removes specific listener
30    let s = state.clone();
31    rp.register_builtin("event.off", move |args, _| {
32        let name = args.first().map(|v| v.to_display_string()).unwrap_or_default();
33        let handler_id = args.get(1).map(|v| v.to_display_string()).unwrap_or_default();
34        let mut events = s.lock().unwrap();
35        if let Some(listeners) = events.get_mut(&name) {
36            let before = listeners.len();
37            listeners.retain(|l| l.handler_id != handler_id);
38            let removed = before - listeners.len();
39            Ok(Value::Bool(removed > 0))
40        } else {
41            Ok(Value::Bool(false))
42        }
43    });
44
45    // event.emit(name, data?) -> returns count of listeners notified
46    let s = state.clone();
47    rp.register_builtin("event.emit", move |args, _| {
48        let name = args.first().map(|v| v.to_display_string()).unwrap_or_default();
49        let mut events = s.lock().unwrap();
50        if let Some(listeners) = events.get_mut(&name) {
51            let count = listeners.len();
52            // Remove once-listeners after emit
53            listeners.retain(|l| !l.once);
54            Ok(Value::Number(count as f64))
55        } else {
56            Ok(Value::Number(0.0))
57        }
58    });
59
60    // event.once(name, handlerId) -> register listener that auto-removes after first emit
61    let s = state.clone();
62    rp.register_builtin("event.once", move |args, _| {
63        let name = args.first().map(|v| v.to_display_string()).unwrap_or_default();
64        let handler_id = args.get(1).map(|v| v.to_display_string()).unwrap_or_default();
65        let mut events = s.lock().unwrap();
66        let listeners = events.entry(name).or_default();
67        listeners.push(EventListener {
68            handler_id: handler_id.clone(),
69            once: true,
70        });
71        Ok(Value::String(handler_id))
72    });
73
74    // event.listenerCount(name) -> number
75    let s = state.clone();
76    rp.register_builtin("event.listenerCount", move |args, _| {
77        let name = args.first().map(|v| v.to_display_string()).unwrap_or_default();
78        let events = s.lock().unwrap();
79        let count = events.get(&name).map(|l| l.len()).unwrap_or(0);
80        Ok(Value::Number(count as f64))
81    });
82
83    // event.removeAll(name?) -> removes all listeners (or all for specific event)
84    let s = state.clone();
85    rp.register_builtin("event.removeAll", move |args, _| {
86        let name = args.first().map(|v| v.to_display_string());
87        let mut events = s.lock().unwrap();
88        if let Some(name) = name {
89            if name.is_empty() || name == "null" {
90                // Remove all events
91                let total: usize = events.values().map(|v| v.len()).sum();
92                events.clear();
93                Ok(Value::Number(total as f64))
94            } else {
95                let count = events.remove(&name).map(|l| l.len()).unwrap_or(0);
96                Ok(Value::Number(count as f64))
97            }
98        } else {
99            let total: usize = events.values().map(|v| v.len()).sum();
100            events.clear();
101            Ok(Value::Number(total as f64))
102        }
103    });
104}