use crate::error::RdiError;
use crate::provider::ServiceProvider;
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ServiceLifetime {
Transient,
Scoped,
Singleton,
}
#[derive(Clone)]
pub struct ServiceDescriptor {
pub type_id: TypeId,
pub type_name: &'static str,
pub key: Option<String>,
pub factory: ServiceFactory,
pub async_factory: Option<AsyncServiceFactory>,
pub lifetime: ServiceLifetime,
}
pub type ServiceStore = HashMap<TypeId, Vec<ServiceEntry>>;
pub trait IServiceResolver: Send + Sync {
fn get_any(&self, key: &str) -> Option<Arc<dyn Any + Send + Sync>>;
fn get_keyed_any(&self, key: &str, variant: &str) -> Option<Arc<dyn Any + Send + Sync>>;
fn get_by_type_id(&self, _tid: TypeId) -> Option<Arc<dyn Any + Send + Sync>> {
None
}
fn get_keyed_by_type_id(
&self,
_tid: TypeId,
_key: &str,
) -> Option<Arc<dyn Any + Send + Sync>> {
None
}
fn get_all_any(&self, _key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
Vec::new()
}
fn provider_arc(&self) -> Option<Arc<ServiceProvider>> {
None
}
fn get<T: ?Sized + Sync + Send + 'static>(&self) -> Result<Arc<T>, RdiError>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
let tid = TypeId::of::<T>();
self.get_by_type_id(tid)
.or_else(|| self.get_any(type_name))
.and_then(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
.ok_or(RdiError::ServiceNotFound { ty: type_name, context: None })
}
fn try_get<T: ?Sized + Sync + Send + 'static>(&self) -> Option<Arc<T>>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
let tid = TypeId::of::<T>();
self.get_by_type_id(tid)
.or_else(|| self.get_any(type_name))
.and_then(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
}
fn get_keyed<T: ?Sized + Sync + Send + 'static>(&self, variant: &str) -> Result<Arc<T>, RdiError>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
let tid = TypeId::of::<T>();
self.get_keyed_by_type_id(tid, variant)
.or_else(|| self.get_keyed_any(type_name, variant))
.and_then(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
.ok_or(RdiError::KeyedServiceNotFound {
key: variant.to_string(),
ty: type_name,
})
}
fn try_get_keyed<T: ?Sized + Sync + Send + 'static>(&self, variant: &str) -> Option<Arc<T>>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
let tid = TypeId::of::<T>();
self.get_keyed_by_type_id(tid, variant)
.or_else(|| self.get_keyed_any(type_name, variant))
.and_then(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
}
fn get_all<T: ?Sized + Sync + Send + 'static>(&self) -> Vec<Arc<T>>
where
Self: Sized,
{
self.get_all_any(std::any::type_name::<T>())
.into_iter()
.filter_map(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
.collect()
}
fn get_owned_any(&self, _key: &str) -> Option<Arc<dyn Any + Send + Sync>> {
None
}
fn get_keyed_owned_any(
&self,
_key: &str,
_variant: &str,
) -> Option<Arc<dyn Any + Send + Sync>> {
None
}
fn get_owned<T: Send + Sync + 'static>(&self) -> Result<T, RdiError>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
let arc_any = self
.get_owned_any(type_name)
.ok_or(RdiError::ServiceNotFound { ty: type_name, context: None })?;
let arc_t: Arc<T> = arc_any
.downcast::<Arc<T>>()
.ok()
.map(|d| Arc::clone(&*d))
.ok_or(RdiError::ServiceNotFound { ty: type_name, context: None })?;
Arc::try_unwrap(arc_t).map_err(|_| RdiError::OwnedNotSupported(type_name))
}
fn try_get_owned<T: Send + Sync + 'static>(&self) -> Option<T>
where
Self: Sized,
{
let arc_any = self.get_owned_any(std::any::type_name::<T>())?;
let arc_t: Arc<T> = arc_any.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d))?;
Arc::try_unwrap(arc_t).ok()
}
fn get_keyed_owned<T: Send + Sync + 'static>(&self, variant: &str) -> Result<T, RdiError>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
let arc_any = self
.get_keyed_owned_any(type_name, variant)
.ok_or(RdiError::KeyedServiceNotFound {
key: variant.to_string(),
ty: type_name,
})?;
let arc_t: Arc<T> = arc_any
.downcast::<Arc<T>>()
.ok()
.map(|d| Arc::clone(&*d))
.ok_or(RdiError::KeyedServiceNotFound {
key: variant.to_string(),
ty: type_name,
})?;
Arc::try_unwrap(arc_t).map_err(|_| RdiError::OwnedNotSupported(type_name))
}
fn try_get_keyed_owned<T: Send + Sync + 'static>(&self, variant: &str) -> Option<T>
where
Self: Sized,
{
let arc_any = self.get_keyed_owned_any(std::any::type_name::<T>(), variant)?;
let arc_t: Arc<T> = arc_any.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d))?;
Arc::try_unwrap(arc_t).ok()
}
}
pub struct ServiceEntry {
pub cache_key: usize,
pub key: Option<String>,
pub type_name: &'static str, pub factory: ServiceFactory,
pub async_factory: Option<AsyncServiceFactory>,
pub lifetime: ServiceLifetime,
}
pub type ServiceFactory =
Arc<dyn Fn(&dyn IServiceResolver) -> Arc<dyn Any + Send + Sync> + Send + Sync>;
pub type AsyncServiceFactory = Arc<
dyn Fn(Arc<ServiceProvider>) -> Pin<Box<dyn Future<Output = Arc<dyn Any + Send + Sync>> + Send>>
+ Send
+ Sync,
>;