use std::{
any::{Any, TypeId},
collections::BTreeMap,
sync::Arc,
};
#[derive(Clone, Default)]
pub struct DependencyStore {
values: BTreeMap<String, Arc<dyn Any + Send + Sync>>,
type_keys: BTreeMap<TypeId, String>,
}
impl DependencyStore {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn insert<T>(&mut self, value: T)
where
T: Send + Sync + 'static,
{
self.insert_named(std::any::type_name::<T>(), value);
}
pub fn insert_arc<T>(&mut self, value: Arc<T>)
where
T: Send + Sync + 'static,
{
self.insert_named_arc(std::any::type_name::<T>(), value);
}
pub fn insert_named<T>(&mut self, name: impl Into<String>, value: T)
where
T: Send + Sync + 'static,
{
self.insert_named_arc(name, Arc::new(value));
}
pub fn insert_named_arc<T>(&mut self, name: impl Into<String>, value: Arc<T>)
where
T: Send + Sync + 'static,
{
let name = name.into();
self.type_keys.insert(TypeId::of::<T>(), name.clone());
self.values.insert(name, value);
}
#[must_use]
pub fn get<T>(&self) -> Option<Arc<T>>
where
T: Send + Sync + 'static,
{
self.type_keys
.get(&TypeId::of::<T>())
.and_then(|name| self.get_named(name))
}
#[must_use]
pub fn get_named<T>(&self, name: &str) -> Option<Arc<T>>
where
T: Send + Sync + 'static,
{
self.values
.get(name)
.cloned()
.and_then(|value| value.downcast::<T>().ok())
}
#[must_use]
pub fn keys(&self) -> Vec<String> {
self.values.keys().cloned().collect()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
}
impl std::fmt::Debug for DependencyStore {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("DependencyStore")
.field("keys", &self.keys())
.finish()
}
}