use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::Arc;
use serde_json::Value;
pub type HandlerId = u64;
pub type EventHandler = Arc<dyn Fn(&[Value])>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SubscriptionResult {
Registered(HandlerId),
Removed,
NotFound,
}
pub trait EventEmitter {
fn on(&self, event: &str, handler: EventHandler) -> HandlerId;
fn once(&self, event: &str, handler: EventHandler) -> HandlerId;
fn off(&self, event: &str, handler_id: HandlerId) -> SubscriptionResult;
fn remove_all_listeners(&self, event: Option<&str>);
fn listener_count(&self, event: &str) -> usize;
fn emit(&self, event: &str, args: &[Value]);
}
#[derive(Clone)]
struct HandlerEntry {
id: HandlerId,
handler: EventHandler,
once: bool,
}
pub struct EventEmitterInner {
handlers: RefCell<HashMap<String, Vec<HandlerEntry>>>,
next_id: RefCell<HandlerId>,
}
impl std::fmt::Debug for EventEmitterInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let count = self.handlers.borrow().len();
f.debug_struct("EventEmitterInner")
.field("event_count", &count)
.finish()
}
}
impl EventEmitterInner {
pub fn new() -> Self {
Self {
handlers: RefCell::new(HashMap::new()),
next_id: RefCell::new(1),
}
}
fn alloc_id(&self) -> HandlerId {
let mut next = self.next_id.borrow_mut();
let id = *next;
*next += 1;
id
}
fn register(&self, event: &str, handler: EventHandler, once: bool) -> HandlerId {
let id = self.alloc_id();
let entry = HandlerEntry { id, handler, once };
self.handlers
.borrow_mut()
.entry(event.to_string())
.or_default()
.push(entry);
id
}
pub fn on(&self, event: &str, handler: EventHandler) -> HandlerId {
self.register(event, handler, false)
}
pub fn once(&self, event: &str, handler: EventHandler) -> HandlerId {
self.register(event, handler, true)
}
pub fn off(&self, event: &str, handler_id: HandlerId) -> SubscriptionResult {
let mut map = self.handlers.borrow_mut();
if let Some(list) = map.get_mut(event) {
let before = list.len();
list.retain(|e| e.id != handler_id);
if list.len() < before {
if list.is_empty() {
map.remove(event);
}
return SubscriptionResult::Removed;
}
}
SubscriptionResult::NotFound
}
pub fn remove_all_listeners(&self, event: Option<&str>) {
let mut map = self.handlers.borrow_mut();
match event {
Some(name) => {
map.remove(name);
}
None => map.clear(),
}
}
pub fn listener_count(&self, event: &str) -> usize {
self.handlers
.borrow()
.get(event)
.map(|v| v.len())
.unwrap_or(0)
}
pub fn emit(&self, event: &str, args: &[Value]) {
let to_call: Vec<(HandlerId, EventHandler, bool)> = {
let map = self.handlers.borrow();
match map.get(event) {
Some(list) => list
.iter()
.map(|e| (e.id, e.handler.clone(), e.once))
.collect(),
None => return,
}
};
let once_ids: Vec<HandlerId> = to_call
.iter()
.filter(|(_, _, o)| *o)
.map(|(id, _, _)| *id)
.collect();
for (_, handler, _) in &to_call {
handler(args);
}
if !once_ids.is_empty() {
let mut map = self.handlers.borrow_mut();
if let Some(list) = map.get_mut(event) {
list.retain(|e| !once_ids.contains(&e.id));
if list.is_empty() {
map.remove(event);
}
}
}
}
}
impl Default for EventEmitterInner {
fn default() -> Self {
Self::new()
}
}
#[macro_export]
macro_rules! delegate_event_emitter {
($self:ident, $field:ident) => {
fn on(
&self,
event: &str,
handler: $crate::api::event_emitter::EventHandler,
) -> $crate::api::event_emitter::HandlerId {
self.$field.on(event, handler)
}
fn once(
&self,
event: &str,
handler: $crate::api::event_emitter::EventHandler,
) -> $crate::api::event_emitter::HandlerId {
self.$field.once(event, handler)
}
fn off(
&self,
event: &str,
handler_id: $crate::api::event_emitter::HandlerId,
) -> $crate::api::event_emitter::SubscriptionResult {
self.$field.off(event, handler_id)
}
fn remove_all_listeners(&self, event: Option<&str>) {
self.$field.remove_all_listeners(event)
}
fn listener_count(&self, event: &str) -> usize {
self.$field.listener_count(event)
}
fn emit(&self, event: &str, args: &[serde_json::Value]) {
self.$field.emit(event, args)
}
};
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::Cell;
use std::rc::Rc;
fn counter_handler() -> (EventHandler, Rc<Cell<u32>>) {
let counter = Rc::new(Cell::new(0u32));
let c = counter.clone();
let handler: EventHandler = Arc::new(move |_args: &[Value]| {
c.set(c.get() + 1);
});
(handler, counter)
}
#[test]
fn on_registers_and_emit_invokes() {
let inner = EventEmitterInner::new();
let (h, counter) = counter_handler();
let id = inner.on("test", h);
assert!(id > 0);
assert_eq!(inner.listener_count("test"), 1);
inner.emit("test", &[]);
assert_eq!(counter.get(), 1);
inner.emit("test", &[]);
assert_eq!(counter.get(), 2);
}
#[test]
fn once_invoked_only_once() {
let inner = EventEmitterInner::new();
let (h, counter) = counter_handler();
inner.once("boom", h);
assert_eq!(inner.listener_count("boom"), 1);
inner.emit("boom", &[]);
assert_eq!(counter.get(), 1);
assert_eq!(inner.listener_count("boom"), 0);
inner.emit("boom", &[]);
assert_eq!(counter.get(), 1);
}
#[test]
fn off_removes_handler() {
let inner = EventEmitterInner::new();
let (h1, c1) = counter_handler();
let (h2, c2) = counter_handler();
let id1 = inner.on("e", h1);
let _id2 = inner.on("e", h2);
assert_eq!(inner.listener_count("e"), 2);
let res = inner.off("e", id1);
assert_eq!(res, SubscriptionResult::Removed);
assert_eq!(inner.listener_count("e"), 1);
inner.emit("e", &[]);
assert_eq!(c1.get(), 0);
assert_eq!(c2.get(), 1);
}
#[test]
fn off_unknown_returns_not_found() {
let inner = EventEmitterInner::new();
let res = inner.off("e", 999);
assert_eq!(res, SubscriptionResult::NotFound);
}
#[test]
fn remove_all_listeners_specific_event() {
let inner = EventEmitterInner::new();
let (h, _) = counter_handler();
inner.on("a", h.clone());
inner.on("b", h);
assert_eq!(inner.listener_count("a"), 1);
assert_eq!(inner.listener_count("b"), 1);
inner.remove_all_listeners(Some("a"));
assert_eq!(inner.listener_count("a"), 0);
assert_eq!(inner.listener_count("b"), 1);
}
#[test]
fn remove_all_listeners_all_events() {
let inner = EventEmitterInner::new();
let (h, _) = counter_handler();
inner.on("a", h.clone());
inner.on("b", h);
inner.remove_all_listeners(None);
assert_eq!(inner.listener_count("a"), 0);
assert_eq!(inner.listener_count("b"), 0);
}
#[test]
fn listener_count_zero_for_unknown_event() {
let inner = EventEmitterInner::new();
assert_eq!(inner.listener_count("nope"), 0);
}
#[test]
fn emit_unknown_event_noop() {
let inner = EventEmitterInner::new();
inner.emit("nope", &[]);
}
#[test]
fn multiple_handlers_called_in_order() {
let inner = EventEmitterInner::new();
let order = Rc::new(RefCell::new(Vec::<u32>::new()));
let o1 = order.clone();
let h1: EventHandler = Arc::new(move |_| o1.borrow_mut().push(1));
let o2 = order.clone();
let h2: EventHandler = Arc::new(move |_| o2.borrow_mut().push(2));
let o3 = order.clone();
let h3: EventHandler = Arc::new(move |_| o3.borrow_mut().push(3));
inner.on("seq", h1);
inner.on("seq", h2);
inner.on("seq", h3);
inner.emit("seq", &[]);
assert_eq!(*order.borrow(), vec![1, 2, 3]);
}
#[test]
fn emit_handler_can_emit_recursively() {
let inner = Rc::new(EventEmitterInner::new());
let counter = Rc::new(Cell::new(0u32));
let inner_clone = inner.clone();
let counter_clone = counter.clone();
let h: EventHandler = Arc::new(move |_args: &[Value]| {
let c = counter_clone.get();
counter_clone.set(c + 1);
if c < 2 {
inner_clone.emit("recurse", &[]);
}
});
inner.on("recurse", h);
inner.emit("recurse", &[]);
assert_eq!(counter.get(), 3);
}
#[test]
fn args_passed_through() {
let inner = EventEmitterInner::new();
let captured = Rc::new(RefCell::new(Vec::<Value>::new()));
let cap = captured.clone();
let h: EventHandler = Arc::new(move |args: &[Value]| {
*cap.borrow_mut() = args.to_vec();
});
inner.on("args", h);
inner.emit("args", &[Value::from(42), Value::from("hi")]);
assert_eq!(captured.borrow().len(), 2);
assert_eq!(captured.borrow()[0], 42);
assert_eq!(captured.borrow()[1], "hi");
}
}