concinnity_core/ecs/
event_store.rs1use alloc::boxed::Box;
7use alloc::collections::BTreeMap;
8use core::any::{Any, TypeId};
9
10use crate::ecs::event::Events;
11
12trait AnyEventQueue: Send {
16 fn update(&mut self);
17 fn as_any(&self) -> &dyn Any;
18 fn as_any_mut(&mut self) -> &mut dyn Any;
19}
20
21impl<E: Send + 'static> AnyEventQueue for Events<E> {
22 fn update(&mut self) {
23 Events::update(self);
24 }
25 fn as_any(&self) -> &dyn Any {
26 self
27 }
28 fn as_any_mut(&mut self) -> &mut dyn Any {
29 self
30 }
31}
32
33#[derive(Default)]
34pub struct EventStore {
36 queues: BTreeMap<TypeId, Box<dyn AnyEventQueue>>,
37}
38
39impl EventStore {
40 pub fn new() -> EventStore {
42 EventStore::default()
43 }
44
45 pub fn get<E: 'static>(&self) -> Option<&Events<E>> {
47 self.queues
48 .get(&TypeId::of::<E>())
49 .and_then(|queue| queue.as_any().downcast_ref::<Events<E>>())
50 }
51
52 pub fn get_mut_or_create<E: Send + 'static>(&mut self) -> &mut Events<E> {
55 self.queues
56 .entry(TypeId::of::<E>())
57 .or_insert_with(|| Box::new(Events::<E>::new()))
58 .as_any_mut()
59 .downcast_mut::<Events<E>>()
60 .expect("queue stored under E's TypeId is Events<E>")
61 }
62
63 pub fn update_all(&mut self) {
66 for queue in self.queues.values_mut() {
67 queue.update();
68 }
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn get_before_first_write_is_none() {
78 let store = EventStore::new();
79 assert!(store.get::<u32>().is_none());
80 }
81
82 #[test]
83 fn queue_persists_across_accesses() {
84 let mut store = EventStore::new();
85 store.get_mut_or_create::<u32>().send(7);
86 assert_eq!(store.get::<u32>().unwrap().len(), 1);
87 assert_eq!(store.get_mut_or_create::<u32>().len(), 1);
89 }
90
91 #[test]
92 fn update_all_rotates_every_queue() {
93 let mut store = EventStore::new();
94 store.get_mut_or_create::<u32>().send(1);
95 store.get_mut_or_create::<&str>().send("a");
96 store.update_all();
99 assert_eq!(store.get::<u32>().unwrap().len(), 1);
100 assert_eq!(store.get::<&str>().unwrap().len(), 1);
101 store.update_all();
102 assert!(store.get::<u32>().unwrap().is_empty());
103 assert!(store.get::<&str>().unwrap().is_empty());
104 }
105}