use std::any::{Any, TypeId}; use hashbrown::HashMap; use nohash_hasher::BuildNoHashHasher; /// A marker trait for signals pub trait UiSignal: Any {} // #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] // pub(crate) struct DummySignal; // impl UiSignal for DummySignal {} pub struct SignalStore { ///XXX: is this truly the most efficient structure? sig: HashMap>, BuildNoHashHasher> } impl SignalStore { /// Create a new [`SigIntStore`] pub(crate) fn new() -> Self { Self { sig: Default::default(), } } /// Ensure that store for given signal type exists and return a mutable reference to it fn internal_store(&mut self) -> &mut Vec> { let type_id = TypeId::of::(); self.sig.entry(type_id).or_default() } /// Add a signal to the store /// /// Signals are stored in the order they are added pub fn add(&mut self, sig: T) { let type_id = TypeId::of::(); if let Some(v) = self.sig.get_mut(&type_id) { v.push(Box::new(sig)); } else { self.sig.insert(type_id, vec![Box::new(sig)]); } } /// Drain all signals of a given type pub(crate) fn drain(&mut self) -> impl Iterator + '_ { self.internal_store::() .drain(..) .map(|x| *x.downcast::().unwrap()) //unchecked? } /// Clear all signals pub(crate) fn clear(&mut self) { //XXX: should we clear the vecs instead? self.sig.clear(); } } //TODO this, simplifies handling signals pub struct SignalTrigger(pub(crate) Box R>); impl SignalTrigger { pub fn new R + 'static>(f: F) -> Self { Self(Box::new(f)) } } impl R + 'static> From for SignalTrigger { fn from(f: T) -> Self { Self(Box::new(f)) } }