mod traits;
use std::{
any::{Any, TypeId, type_name},
collections::HashMap,
sync::Arc,
};
use crate::DependencyInjectionError;
use parking_lot::RwLock;
pub use traits::*;
#[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,
{
let map = self.inner.read();
let type_name = type_name::<T>().to_string();
let state_ref = map.get(&TypeId::of::<T>()).ok_or(
DependencyInjectionError::DependencyNotFound {
type_name: type_name.clone(),
},
)?;
state_ref
.downcast_ref::<T>()
.cloned()
.ok_or(DependencyInjectionError::DependencyNotFound { type_name })
}
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(
DependencyInjectionError::DependencyNotFound {
type_name: type_name.clone(),
},
)?;
state_ref
.clone()
.downcast::<T>()
.map_err(|_| DependencyInjectionError::DependencyNotFound { type_name })
}
pub fn insert<T: Send + Sync + 'static>(&self, state: T) {
self.inner
.write()
.insert(TypeId::of::<T>(), Arc::new(state));
}
pub 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()
}
}