hUI/hui/src/signal.rs

50 lines
1.4 KiB
Rust
Raw Normal View History

2024-03-11 18:29:26 -05:00
use std::any::{Any, TypeId};
use hashbrown::HashMap;
use nohash_hasher::BuildNoHashHasher;
/// A marker trait for signals
pub trait UiSignal: Any {}
2024-03-11 19:26:48 -05:00
// #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
// pub(crate) struct DummySignal;
// impl UiSignal for DummySignal {}
2024-03-11 18:29:26 -05:00
2024-03-11 19:26:48 -05:00
pub struct SignalStore {
2024-03-11 18:29:26 -05:00
///XXX: is this truly the most efficient structure?
sig: HashMap<TypeId, Vec<Box<dyn Any>>, BuildNoHashHasher<u64>>
}
2024-03-11 19:26:48 -05:00
impl SignalStore {
2024-03-11 18:29:26 -05:00
/// Create a new [`SigIntStore`]
2024-03-11 19:26:48 -05:00
pub(crate) fn new() -> Self {
2024-03-11 18:29:26 -05:00
Self {
sig: Default::default(),
}
}
/// Ensure that store for given signal type exists and return a mutable reference to it
fn internal_store<T: UiSignal + 'static>(&mut self) -> &mut Vec<Box<dyn Any>> {
let type_id = TypeId::of::<T>();
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<T: UiSignal + 'static>(&mut self, sig: T) {
let type_id = TypeId::of::<T>();
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
2024-03-11 19:26:48 -05:00
pub(crate) fn drain<T: UiSignal + 'static>(&mut self) -> impl Iterator<Item = T> + '_ {
2024-03-11 18:29:26 -05:00
self.internal_store::<T>()
.drain(..)
.map(|x| *x.downcast::<T>().unwrap()) //unchecked?
}
}