#[cfg(feature = "axum")]
pub mod axum;
pub mod error;
pub mod scope;
#[cfg(feature = "axum")]
pub use axum::*;
#[cfg(feature = "jav")]
pub mod jav;
#[cfg(feature = "jav")]
pub use jav::*;
use std::{
any::{Any, TypeId},
collections::HashMap,
sync::{Arc, OnceLock},
};
use arc_swap::ArcSwapOption;
use crate::{
error::{ServiceAlreadyExistsError, ServiceNotFoundError},
scope::{Scope, ScopeProvider, get_default_scope_full},
};
pub struct DI<T: Send + Sync + 'static>(pub Arc<T>);
pub struct DIK<T: Send + Sync + 'static, K: 'static>(pub Arc<T>, std::marker::PhantomData<K>);
#[derive(Clone)]
pub enum Service {
Singleton(Arc<dyn Any + Send + Sync>),
Transient(Arc<dyn Fn() -> Arc<dyn Any + Send + Sync> + Send + Sync>),
Scoped(Arc<dyn Fn() -> Arc<dyn Any + Send + Sync> + Send + Sync>),
}
#[derive(Clone)]
pub struct ServiceCollection {
collection: HashMap<(TypeId, Option<TypeId>), Service>,
}
impl ServiceCollection {
pub fn new() -> Self {
Self {
collection: HashMap::new(),
}
}
pub fn add_singleton<T: Send + Sync + 'static>(
&mut self,
service: T,
) -> Result<(), ServiceAlreadyExistsError> {
self.add_internal::<T>(Service::Singleton(Arc::new(service)), None)
}
pub fn add_singleton_keyed<T: Send + Sync + 'static>(
&mut self,
service: T,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError> {
self.add_internal::<T>(Service::Singleton(Arc::new(service)), Some(key))
}
fn add_internal<T: Send + Sync + 'static>(
&mut self,
service: Service,
key: Option<TypeId>,
) -> Result<(), ServiceAlreadyExistsError> {
let tid = (TypeId::of::<T>(), key);
if self.collection.contains_key(&tid) {
return Err(ServiceAlreadyExistsError);
}
self.collection.insert(tid, service);
Ok(())
}
pub fn add_transient<T: Send + Sync + 'static, F>(
&mut self,
service_factory: F,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> T + Send + Sync + 'static,
{
self.add_internal::<T>(
Service::Transient(Arc::new(move || Arc::new(service_factory()))),
None,
)
}
pub fn add_transient_keyed<T: Send + Sync + 'static, F>(
&mut self,
service_factory: F,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> T + Send + Sync + 'static,
{
self.add_internal::<T>(
Service::Transient(Arc::new(move || Arc::new(service_factory()))),
Some(key),
)
}
pub fn add_scoped<T: Send + Sync + 'static, F>(
&mut self,
service_factory: F,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> T + Send + Sync + 'static,
{
self.add_internal::<T>(
Service::Scoped(Arc::new(move || Arc::new(service_factory()))),
None,
)
}
pub fn add_scoped_keyed<T: Send + Sync + 'static, F>(
&mut self,
service_factory: F,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> T + Send + Sync + 'static,
{
self.add_internal::<T>(
Service::Scoped(Arc::new(move || Arc::new(service_factory()))),
Some(key),
)
}
pub fn create_scope(&self) -> Arc<Scope> {
let mut scope: Scope = HashMap::new();
self.collection
.iter()
.filter(|(_, v)| match v {
Service::Scoped(_) => true,
_ => false,
})
.for_each(|(k, _)| {
scope.insert(k.clone(), OnceLock::new());
});
Arc::new(scope)
}
fn di_internal<T: Send + Sync + 'static>(
&self,
key: Option<TypeId>,
scope: Option<Arc<Arc<dyn ScopeProvider>>>,
) -> Result<Arc<T>, ServiceNotFoundError> {
let tid = (TypeId::of::<T>(), key);
if let Some(s) = self.collection.get(&tid) {
match s {
Service::Singleton(service) if let Ok(res) = service.clone().downcast() => Ok(res),
Service::Transient(factory) if let Ok(res) = factory.clone()().downcast() => {
Ok(res)
},
Service::Scoped(factory) => {
let scope = scope
.unwrap_or_else(|| get_default_scope_full())
.provide_scope()?;
let Some(res) = scope.get(&tid) else {
return Err(ServiceNotFoundError);
};
res.get_or_init(|| factory.clone()())
.clone()
.downcast()
.map_err(|_| ServiceNotFoundError)
},
_ => Err(ServiceNotFoundError),
}
} else {
Err(ServiceNotFoundError)
}
}
pub fn di<T: Send + Sync + 'static>(&self) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(None, None)
}
pub fn dik<T: Send + Sync + 'static, K: 'static>(
&self,
) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(Some(TypeId::of::<K>()), None)
}
pub fn dis<T: Send + Sync + 'static>(
&self,
scope: Arc<Arc<dyn ScopeProvider>>,
) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(None, Some(scope))
}
pub fn disk<T: Send + Sync + 'static, K: 'static>(
&self,
scope: Arc<Arc<dyn ScopeProvider>>,
) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(Some(TypeId::of::<K>()), Some(scope))
}
}
static SERVICE_PROVIDER: ArcSwapOption<ServiceCollection> = ArcSwapOption::const_empty();
pub fn sp() -> Option<Arc<ServiceCollection>> {
SERVICE_PROVIDER.load_full()
}
pub fn spp() -> Arc<ServiceCollection> {
sp().expect("ServiceProvider not yet initialized")
}
pub fn set_sp(sp: ServiceCollection) -> Option<Arc<ServiceCollection>> {
set_sp_arc(Arc::new(sp))
}
pub fn set_sp_arc(sp: Arc<ServiceCollection>) -> Option<Arc<ServiceCollection>> {
SERVICE_PROVIDER.swap(Some(sp))
}