1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
// Creates a simple `Any` map registry of objects by type.
// These methods `panic!` because it immediately bubbles up that
// the order of operations for application state is wrong, and
// that systems should be registered correctly.
#[macro_export]
macro_rules! create_instance_manager {
($manager:ident, $type:ident) => {
pub trait $type: Any {}
#[derive(Debug, Default)]
pub struct $manager {
cache: FxHashMap<TypeId, Box<dyn Any + Sync + Send>>,
}
impl $manager {
/// Get an immutable instance reference for the provided type.
/// If the instance does not exist, a panic will be triggered.
pub fn get<T: Any + Send + Sync + $type>(&self) -> &T {
if let Some(value) = self.cache.get(&TypeId::of::<T>()) {
return value.downcast_ref::<T>().unwrap();
}
panic!("{} does not exist!", type_name::<T>())
}
/// Get a mutable instance reference for the provided type.
/// If the instance does not exist, a panic will be triggered.
pub fn get_mut<T: Any + Send + Sync + $type>(&mut self) -> &mut T {
if let Some(value) = self.cache.get_mut(&TypeId::of::<T>()) {
return value.downcast_mut::<T>().unwrap();
}
panic!("{} does not exist!", type_name::<T>())
}
/// Set the instance into the registry with the provided type.
/// If an exact type already exists, it'll be overwritten.
pub fn set<T: Any + Send + Sync + $type>(&mut self, instance: T) -> &mut Self {
self.cache.insert(TypeId::of::<T>(), Box::new(instance));
self
}
}
};
}