use std::any::Any;
use std::collections::{HashMap, VecDeque};
pub type EventId = &'static str;
pub type Subscription = usize;
pub type EventData = Box<dyn Any + Send>;
#[derive(Debug)]
pub struct Event {
pub id: EventId,
data: Option<EventData>,
}
impl Event {
pub fn data<T: 'static>(&self) -> Option<&T> {
self.data.as_ref().and_then(|d| d.downcast_ref::<T>())
}
pub fn take_data<T: 'static>(&mut self) -> Option<T> {
self.data
.take()
.and_then(|d| d.downcast::<T>().ok())
.map(|b| *b)
}
}
#[derive(Default)]
pub struct EventBus {
queue: VecDeque<Event>,
filters: HashMap<EventId, bool>,
}
impl EventBus {
pub fn new() -> Self {
Self::default()
}
pub fn emit<T: Send + 'static>(&mut self, id: EventId, data: T) {
self.queue.push_back(Event {
id,
data: Some(Box::new(data)),
});
}
pub fn emit_signal(&mut self, id: EventId) {
self.queue.push_back(Event { id, data: None });
}
pub fn poll(&mut self) -> Option<Event> {
self.queue.pop_front()
}
pub fn poll_id(&mut self, target_id: EventId) -> Option<Event> {
if let Some(pos) = self.queue.iter().position(|e| e.id == target_id) {
self.queue.remove(pos)
} else {
None
}
}
pub fn has_events(&self) -> bool {
!self.queue.is_empty()
}
pub fn event_count(&self) -> usize {
self.queue.len()
}
pub fn clear(&mut self) {
self.queue.clear();
}
pub fn subscribe(&mut self, id: EventId) -> Subscription {
self.filters.insert(id, true);
self.filters.len()
}
pub fn unsubscribe(&mut self, id: EventId) {
self.filters.remove(id);
}
pub fn is_subscribed(&self, id: EventId) -> bool {
self.filters.get(id).copied().unwrap_or(false)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_emit_and_poll() {
let mut bus = EventBus::new();
bus.emit("test", 42i32);
assert!(bus.has_events());
let event = bus.poll().unwrap();
assert_eq!(event.id, "test");
assert_eq!(event.data::<i32>(), Some(&42));
assert!(!bus.has_events());
}
#[test]
fn test_emit_signal() {
let mut bus = EventBus::new();
bus.emit_signal("ping");
let event = bus.poll().unwrap();
assert_eq!(event.id, "ping");
assert!(event.data::<()>().is_none());
}
#[test]
fn test_multiple_events() {
let mut bus = EventBus::new();
bus.emit("a", 1i32);
bus.emit("b", 2i32);
bus.emit("c", 3i32);
assert_eq!(bus.event_count(), 3);
let e1 = bus.poll().unwrap();
assert_eq!(e1.id, "a");
let e2 = bus.poll().unwrap();
assert_eq!(e2.id, "b");
let e3 = bus.poll().unwrap();
assert_eq!(e3.id, "c");
}
#[test]
fn test_poll_by_id() {
let mut bus = EventBus::new();
bus.emit("first", 1i32);
bus.emit("target", 2i32);
bus.emit("third", 3i32);
let target = bus.poll_id("target").unwrap();
assert_eq!(target.data::<i32>(), Some(&2));
assert_eq!(bus.event_count(), 2);
}
#[test]
fn test_typed_data() {
#[derive(Debug, PartialEq)]
struct MyEvent {
value: String,
}
let mut bus = EventBus::new();
bus.emit(
"custom",
MyEvent {
value: "hello".into(),
},
);
let event = bus.poll().unwrap();
let data = event.data::<MyEvent>().unwrap();
assert_eq!(data.value, "hello");
}
#[test]
fn test_take_data() {
let mut bus = EventBus::new();
bus.emit("test", 42i32);
let mut event = bus.poll().unwrap();
let data = event.take_data::<i32>().unwrap();
assert_eq!(data, 42);
assert!(event.take_data::<i32>().is_none());
}
#[test]
fn test_clear_events() {
let mut bus = EventBus::new();
bus.emit("a", 1i32);
bus.emit("b", 2i32);
assert_eq!(bus.event_count(), 2);
bus.clear();
assert_eq!(bus.event_count(), 0);
assert!(!bus.has_events());
}
#[test]
fn test_subscribe_unsubscribe() {
let mut bus = EventBus::new();
assert!(!bus.is_subscribed("my_event"));
bus.subscribe("my_event");
assert!(bus.is_subscribed("my_event"));
bus.unsubscribe("my_event");
assert!(!bus.is_subscribed("my_event"));
}
#[test]
fn test_multiple_subscriptions() {
let mut bus = EventBus::new();
bus.subscribe("event_a");
bus.subscribe("event_b");
bus.subscribe("event_c");
assert!(bus.is_subscribed("event_a"));
assert!(bus.is_subscribed("event_b"));
assert!(bus.is_subscribed("event_c"));
assert!(!bus.is_subscribed("event_d"));
}
#[test]
fn test_default_event_bus() {
let bus = EventBus::default();
assert!(!bus.has_events());
assert_eq!(bus.event_count(), 0);
}
#[test]
fn test_poll_empty_returns_none() {
let mut bus = EventBus::new();
assert!(bus.poll().is_none());
assert!(bus.poll_id("test").is_none());
}
#[test]
fn test_event_data_none_for_signal() {
let mut bus = EventBus::new();
bus.emit_signal("signal");
let event = bus.poll().unwrap();
assert!(event.data::<i32>().is_none());
}
#[test]
fn test_wrong_type_downcast() {
let mut bus = EventBus::new();
bus.emit("test", 42i32);
let event = bus.poll().unwrap();
assert!(event.data::<String>().is_none());
}
}