use std::{
any::{Any, TypeId},
collections::HashMap,
sync::Mutex,
};
use lazy_static::lazy_static;
lazy_static! {
static ref REGISTRY: Mutex<HashMap<TypeId, Box<dyn Any + Send>>> = Mutex::new(HashMap::new());
}
pub struct Registry<T> {
_use: Option<T>,
}
impl<T: Send + 'static> Registry<T> {
pub fn register(key: &str, value: T) {
let mut registry = REGISTRY.lock().unwrap();
if !registry.contains_key(&TypeId::of::<T>()) {
let map: HashMap<String, T> = HashMap::new();
registry.insert(TypeId::of::<T>(), Box::new(map));
}
let map = registry
.get_mut(&TypeId::of::<T>())
.unwrap()
.downcast_mut::<HashMap<String, T>>()
.unwrap();
map.insert(key.to_string(), value);
}
pub fn apply<R, F: FnOnce(&mut T) -> R>(key: &str, f: F) -> Option<R> {
let mut registry = REGISTRY.lock().unwrap();
let map = registry
.get_mut(&TypeId::of::<T>())?
.downcast_mut::<HashMap<String, T>>()?;
let value = map.get_mut(key)?;
Some(f(value))
}
pub fn remove(key: &str) -> Option<T> {
let mut registry = REGISTRY.lock().unwrap();
let map = registry
.get_mut(&TypeId::of::<T>())?
.downcast_mut::<HashMap<String, T>>()?;
map.remove(key)
}
}