use std::{ any::{Any, TypeId}, collections::HashMap, mem, ops::DerefMut, }; pub struct Events { events: HashMap< TypeId, ( Vec>, Vec anyhow::Result<()> + Send + Sync>>, ), >, } impl Default for Events { fn default() -> Self { Self { events: HashMap::new(), } } } impl Events { pub(crate) fn clone_from_register(&self) -> Self { Self { events: self .events .keys() .map(|type_id| (*type_id, (Vec::new(), Vec::new()))) .collect(), } } pub(crate) fn move_events(&mut self, other: &mut Self) { for (type_id, (payloads, _)) in other.events.iter_mut() { if !payloads.is_empty() { let mut tmp = Vec::new(); mem::swap(payloads, &mut tmp); self.events.get_mut(type_id).unwrap().0.extend(tmp); } } } 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 C, &T) -> anyhow::Result<()> + Send + Sync + 'static, { match self.events.get_mut(&TypeId::of::()) { Some((_, listener)) => listener.push(Box::new(move |c, payload| { let typed_payload: &T = payload.downcast_ref().unwrap(); f(c, 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, c: &mut C) -> anyhow::Result<()> { for (payloads, listeners) in self.events.values_mut() { for payload in payloads.iter_mut() { for listener in listeners.iter_mut() { (listener)(c, payload.deref_mut())?; } } payloads.clear(); } Ok(()) } }