use crate::error::RdiError;
use crate::key::ServiceKey;
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<ServiceKey>,
pub factory: ServiceFactory,
pub keyed_factory: Option<KeyedServiceFactory>,
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 get_all_keyed_any(&self, _key: &str) -> Vec<Arc<dyn Any + Send + Sync>> {
Vec::new()
}
fn get_all_any_result(&self, key: &str) -> Result<Vec<Arc<dyn Any + Send + Sync>>, RdiError> {
Ok(self.get_all_any(key))
}
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_else(|| RdiError::not_found(type_name, None))
}
fn try_get<T: ?Sized + Sync + Send + 'static>(&self) -> Option<Arc<T>>
where
Self: Sized,
{
let type_name = std::any::type_name::<T>();
self.try_get_any_result(type_name)
.ok()
.flatten()
.and_then(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
}
fn try_get_any_result(
&self,
key: &str,
) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
Ok(self.get_any(key))
}
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_else(|| RdiError::keyed_not_found(type_name, variant, None))
}
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>();
self.try_get_keyed_any_result(type_name, variant)
.ok()
.flatten()
.and_then(|a| a.downcast::<Arc<T>>().ok().map(|d| Arc::clone(&*d)))
}
fn try_get_keyed_any_result(
&self,
key: &str,
variant: &str,
) -> Result<Option<Arc<dyn Any + Send + Sync>>, RdiError> {
Ok(self.get_keyed_any(key, variant))
}
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_else(|| RdiError::not_found(type_name, None))?;
let arc_t: Arc<T> = arc_any
.downcast::<Arc<T>>()
.ok()
.map(|d| Arc::clone(&*d))
.ok_or_else(|| RdiError::not_found(type_name, 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_else(|| RdiError::keyed_not_found(type_name, variant, None))?;
let arc_t: Arc<T> = arc_any
.downcast::<Arc<T>>()
.ok()
.map(|d| Arc::clone(&*d))
.ok_or_else(|| RdiError::keyed_not_found(type_name, variant, None))?;
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<ServiceKey>,
pub type_name: &'static str, pub factory: ServiceFactory,
pub keyed_factory: Option<KeyedServiceFactory>,
pub async_factory: Option<AsyncServiceFactory>,
pub lifetime: ServiceLifetime,
}
impl ServiceEntry {
pub(crate) fn is_async(&self) -> bool {
self.async_factory.is_some()
}
pub(crate) fn is_any_key(&self) -> bool {
self.key.as_ref().is_some_and(ServiceKey::is_any)
}
}
pub type ServiceFactory =
Arc<dyn Fn(&dyn IServiceResolver) -> Arc<dyn Any + Send + Sync> + Send + Sync>;
pub type KeyedServiceFactory =
Arc<dyn Fn(&dyn IServiceResolver, &ServiceKey) -> 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,
>;