use std::{ any::{Any, TypeId}, collections::HashMap, ops::DerefMut, sync::Arc, }; use crate::World; pub struct Events { events: HashMap< TypeId, // TypeId of Payload ( Vec>, // Payload Vec anyhow::Result<()> + Send + Sync>>, // Listener on Payload ), >, } impl Default for Events { fn default() -> Self { Self { events: HashMap::new(), } } } impl Events { pub(crate) fn take_events(&mut self) -> Self { Self { events: self .events .iter_mut() .filter_map(|(type_id, (payload, listener))| { (!payload.is_empty()) .then(|| (*type_id, (std::mem::take(payload), listener.clone()))) }) .collect(), } } pub fn clear(&mut self) { for (payloads, listener) in self.events.values_mut() { payloads.clear(); listener.clear(); } } pub fn register_event(&mut self) { self.events .insert(TypeId::of::(), (Vec::new(), Vec::new())); } pub fn add_reader(&mut self, f: F) where F: Fn(&mut World, &T) -> anyhow::Result<()> + Send + Sync + 'static, { match self.events.get_mut(&TypeId::of::()) { Some((_, listener)) => listener.push(Arc::new(move |world, payload| { let typed_payload: &T = payload.downcast_ref().unwrap(); f(world, typed_payload) })), None => panic!("register event type first!"), } } pub fn write_event(&mut self, payload: T) { match self.events.get_mut(&TypeId::of::()) { Some((payloads, _)) => payloads.push(Box::new(payload)), None => panic!("register event type first!"), } } pub(crate) fn fire_events(&mut self, world: &mut World) -> anyhow::Result<()> { for (payloads, listeners) in self.events.values_mut() { for payload in payloads.iter_mut() { for listener in listeners.iter_mut() { (listener)(world, payload.deref_mut())?; } } payloads.clear(); } Ok(()) } }