#[cfg(feature = "axum")]
pub mod axum;
pub mod error;
#[cfg(feature = "jav")]
pub mod jav;
pub mod scope;
use std::{
any::{Any, TypeId},
sync::{Arc, OnceLock},
};
use arc_swap::ArcSwapOption;
use scc::HashMap;
use crate::{
error::{ServiceAlreadyExistsError, ServiceNotFoundError},
scope::{Scope, ScopeProvider, get_default_scope_full},
};
pub struct DI<T: ?Sized + Send + Sync + 'static>(pub Arc<T>);
pub struct DIK<T: ?Sized + Send + Sync + 'static, K: 'static>(
pub Arc<T>,
pub 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>(
&self,
service: T,
) -> Result<(), ServiceAlreadyExistsError> {
self.add_internal::<T>(Service::Singleton(Arc::new(Arc::new(service))), None)
}
pub fn add_singleton_keyed<T: Send + Sync + 'static>(
&self,
service: T,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError> {
self.add_internal::<T>(Service::Singleton(Arc::new(Arc::new(service))), Some(key))
}
pub fn add_singleton_trait<Trait: ?Sized + Send + Sync + 'static>(
&self,
service: Arc<Trait>,
) -> Result<(), ServiceAlreadyExistsError> {
self.add_internal::<Trait>(Service::Singleton(Arc::new(service)), None)
}
pub fn add_singleton_trait_keyed<Trait: ?Sized + Send + Sync + 'static>(
&self,
service: Arc<Trait>,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError> {
self.add_internal::<Trait>(Service::Singleton(Arc::new(service)), Some(key))
}
fn add_internal<T: ?Sized + Send + Sync + 'static>(
&self,
service: Service,
key: Option<TypeId>,
) -> Result<(), ServiceAlreadyExistsError> {
let tid = (TypeId::of::<T>(), key);
if self.collection.contains_sync(&tid) {
return Err(ServiceAlreadyExistsError);
}
let _ = self.collection.insert_sync(tid, service);
Ok(())
}
pub fn add_transient<T: Send + Sync + 'static, F>(
&self,
service_factory: F,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> T + Send + Sync + 'static,
{
self.add_internal::<T>(
Service::Transient(Arc::new(move || Arc::new(Arc::new(service_factory())))),
None,
)
}
pub fn add_transient_keyed<T: Send + Sync + 'static, F>(
&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(Arc::new(service_factory())))),
Some(key),
)
}
pub fn add_transient_trait<Trait: ?Sized + Send + Sync + 'static, F>(
&self,
service_factory: F,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> Arc<Trait> + Send + Sync + 'static,
{
self.add_internal::<Trait>(
Service::Transient(Arc::new(move || Arc::new(service_factory()))),
None,
)
}
pub fn add_transient_trait_keyed<Trait: ?Sized + Send + Sync + 'static, F>(
&self,
service_factory: F,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> Arc<Trait> + Send + Sync + 'static,
{
self.add_internal::<Trait>(
Service::Transient(Arc::new(move || Arc::new(service_factory()))),
Some(key),
)
}
pub fn add_scoped<T: Send + Sync + 'static, F>(
&self,
service_factory: F,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> T + Send + Sync + 'static,
{
self.add_internal::<T>(
Service::Scoped(Arc::new(move || Arc::new(Arc::new(service_factory())))),
None,
)
}
pub fn add_scoped_keyed<T: Send + Sync + 'static, F>(
&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(Arc::new(service_factory())))),
Some(key),
)
}
pub fn add_scoped_trait<Trait: ?Sized + Send + Sync + 'static, F>(
&self,
service_factory: F,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> Arc<Trait> + Send + Sync + 'static,
{
self.add_internal::<Trait>(
Service::Scoped(Arc::new(move || Arc::new(service_factory()))),
None,
)
}
pub fn add_scoped_trait_keyed<Trait: ?Sized + Send + Sync + 'static, F>(
&self,
service_factory: F,
key: TypeId,
) -> Result<(), ServiceAlreadyExistsError>
where
F: Fn() -> Arc<Trait> + Send + Sync + 'static,
{
self.add_internal::<Trait>(
Service::Scoped(Arc::new(move || Arc::new(service_factory()))),
Some(key),
)
}
pub fn create_scope(&self) -> Arc<Scope> {
let scope: Scope = HashMap::new();
self.collection.iter_sync(|k, v| {
let Service::Scoped(_) = v else {
return true;
};
let _ = scope.insert_sync(k.clone(), OnceLock::new());
true
});
Arc::new(scope)
}
fn di_internal<T: ?Sized + 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.read_sync(&tid, |_, s| match s {
Service::Singleton(service) if let Ok(res) = service.clone().downcast::<Arc<T>>() => {
Ok((*res).clone())
},
Service::Transient(factory) => {
let instance = factory.clone()();
if let Ok(res) = instance.downcast::<Arc<T>>() {
Ok((*res).clone())
} else {
Err(ServiceNotFoundError)
}
},
Service::Scoped(factory) => {
let scope = scope
.unwrap_or_else(|| get_default_scope_full())
.provide_scope()?;
let Some(res) = scope.get_sync(&tid) else {
return Err(ServiceNotFoundError);
};
let instance = res.get_or_init(|| factory.clone()()).clone();
if let Ok(res) = instance.downcast::<Arc<T>>() {
Ok((*res).clone())
} else {
Err(ServiceNotFoundError)
}
},
_ => Err(ServiceNotFoundError),
}) {
return s;
} else {
Err(ServiceNotFoundError)
}
}
pub fn dir<T: ?Sized + Send + Sync + 'static>(&self) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(None, None)
}
pub fn dikr<T: ?Sized + Send + Sync + 'static, K: 'static>(
&self,
) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(Some(TypeId::of::<K>()), None)
}
pub fn disr<T: ?Sized + Send + Sync + 'static>(
&self,
scope: Arc<Arc<dyn ScopeProvider>>,
) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(None, Some(scope))
}
pub fn diskr<T: ?Sized + Send + Sync + 'static, K: 'static>(
&self,
scope: Arc<Arc<dyn ScopeProvider>>,
) -> Result<Arc<T>, ServiceNotFoundError> {
self.di_internal(Some(TypeId::of::<K>()), Some(scope))
}
pub fn di<T: ?Sized + Send + Sync + 'static>(&self) -> Arc<T> {
self.di_internal(None, None)
.expect("Failed to find service")
}
pub fn dik<T: ?Sized + Send + Sync + 'static, K: 'static>(&self) -> Arc<T> {
self.di_internal(Some(TypeId::of::<K>()), None)
.expect("Failed to find service")
}
pub fn dis<T: ?Sized + Send + Sync + 'static>(
&self,
scope: Arc<Arc<dyn ScopeProvider>>,
) -> Arc<T> {
self.di_internal(None, Some(scope))
.expect("Failed to find service")
}
pub fn disk<T: ?Sized + Send + Sync + 'static, K: 'static>(
&self,
scope: Arc<Arc<dyn ScopeProvider>>,
) -> Arc<T> {
self.di_internal(Some(TypeId::of::<K>()), Some(scope))
.expect("Failed to find service")
}
}
static SERVICE_PROVIDER: ArcSwapOption<ServiceCollection> = ArcSwapOption::const_empty();
pub fn spo() -> Option<Arc<ServiceCollection>> {
SERVICE_PROVIDER.load_full()
}
pub fn sp() -> Arc<ServiceCollection> {
spo().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))
}
pub fn init_sp() {
set_sp(ServiceCollection::new());
}