use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::Arc;
pub struct Container {
services: HashMap<TypeId, Box<dyn Any + Send + Sync>>,
named: HashMap<(TypeId, String), Box<dyn Any + Send + Sync>>,
}
impl Default for Container {
fn default() -> Self {
Self::new()
}
}
impl Container {
pub fn new() -> Self {
Container {
services: HashMap::new(),
named: HashMap::new(),
}
}
pub fn register<T: Send + Sync + 'static>(&mut self, service: T) -> &mut Self {
self.services
.insert(TypeId::of::<T>(), Box::new(Arc::new(service)));
self
}
pub fn provide<T>(&mut self, service: Arc<T>) -> &mut Self
where
T: ?Sized + Send + Sync + 'static,
{
let boxed: Box<dyn Any + Send + Sync> = Box::new(service);
self.services.insert(TypeId::of::<T>(), boxed);
self
}
pub fn register_named<T: Send + Sync + 'static>(
&mut self,
name: impl Into<String>,
service: T,
) -> &mut Self {
self.named.insert(
(TypeId::of::<T>(), name.into()),
Box::new(Arc::new(service)),
);
self
}
pub fn provide_named<T>(
&mut self,
name: impl Into<String>,
service: Arc<T>,
) -> &mut Self
where
T: ?Sized + Send + Sync + 'static,
{
let boxed: Box<dyn Any + Send + Sync> = Box::new(service);
self.named.insert((TypeId::of::<T>(), name.into()), boxed);
self
}
pub fn get<T>(&self) -> Option<Arc<T>>
where
T: ?Sized + 'static,
Arc<T>: Clone,
{
self.services
.get(&TypeId::of::<T>())
.and_then(|b| b.downcast_ref::<Arc<T>>())
.cloned()
}
pub fn get_named<T>(&self, name: &str) -> Option<Arc<T>>
where
T: ?Sized + 'static,
Arc<T>: Clone,
{
self.named
.get(&(TypeId::of::<T>(), name.to_string()))
.and_then(|b| b.downcast_ref::<Arc<T>>())
.cloned()
}
pub fn contains<T: ?Sized + 'static>(&self) -> bool {
self.services.contains_key(&TypeId::of::<T>())
}
pub fn contains_named<T: ?Sized + 'static>(&self, name: &str) -> bool {
self.named
.contains_key(&(TypeId::of::<T>(), name.to_string()))
}
pub fn len(&self) -> usize {
self.services.len()
}
pub fn is_empty(&self) -> bool {
self.services.is_empty()
}
pub fn into_arc(self) -> Arc<Self> {
Arc::new(self)
}
}
#[cfg(test)]
mod tests;