use std::{
any::{Any, TypeId, type_name},
collections::HashMap,
sync::Arc,
};
use crate::DependencyInjectionError;
use parking_lot::RwLock;
#[derive(Clone, Debug)]
pub struct State {
inner: Arc<RwLock<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>>,
}
impl State {
pub fn new() -> Self {
Self {
inner: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn get<T>(&self) -> Result<T, DependencyInjectionError>
where
T: Clone + Send + Sync + 'static,
{
self.borrow::<T>().map(|value| (*value).clone())
}
pub fn borrow<T>(&self) -> Result<Arc<T>, DependencyInjectionError>
where
T: Send + Sync + 'static,
{
let map = self.inner.read();
let type_name = type_name::<T>().to_string();
let state_ref = map
.get(&TypeId::of::<T>())
.ok_or_else(|| DependencyInjectionError::dependency_not_found(type_name.clone()))?;
state_ref
.clone()
.downcast::<T>()
.map_err(|_| DependencyInjectionError::dependency_not_found(type_name))
}
pub fn insert<T: Send + Sync + 'static>(&self, state: T) {
self.inner
.write()
.insert(TypeId::of::<T>(), Arc::new(state));
}
pub(crate) fn insert_instance(&self, type_id: TypeId, instance: Arc<dyn Any + Send + Sync>) {
self.inner.write().insert(type_id, instance);
}
}
impl Default for State {
fn default() -> Self {
Self::new()
}
}