use std::marker::PhantomData; use std::sync::Arc; use async_trait::async_trait; use crate::async_di_container::AsyncDIContainer; use crate::errors::injectable::InjectableError; use crate::interfaces::async_injectable::AsyncInjectable; use crate::ptr::{ThreadsafeSingletonPtr, TransientPtr}; #[derive(strum_macros::Display, Debug)] pub enum AsyncProvidable { Transient(TransientPtr), Singleton(ThreadsafeSingletonPtr), #[cfg(feature = "factory")] Factory( crate::ptr::ThreadsafeFactoryPtr< dyn crate::interfaces::any_factory::AnyThreadsafeFactory, >, ), #[cfg(feature = "factory")] DefaultFactory( crate::ptr::ThreadsafeFactoryPtr< dyn crate::interfaces::any_factory::AnyThreadsafeFactory, >, ), #[cfg(feature = "factory")] AsyncDefaultFactory( crate::ptr::ThreadsafeFactoryPtr< dyn crate::interfaces::any_factory::AnyThreadsafeFactory, >, ), } #[async_trait] pub trait IAsyncProvider: Send + Sync { async fn provide( &self, di_container: &Arc, dependency_history: Vec<&'static str>, ) -> Result; fn do_clone(&self) -> Box; } impl Clone for Box { fn clone(&self) -> Self { self.do_clone() } } pub struct AsyncTransientTypeProvider where InjectableType: AsyncInjectable, { injectable_phantom: PhantomData, } impl AsyncTransientTypeProvider where InjectableType: AsyncInjectable, { pub fn new() -> Self { Self { injectable_phantom: PhantomData, } } } #[async_trait] impl IAsyncProvider for AsyncTransientTypeProvider where InjectableType: AsyncInjectable, { async fn provide( &self, di_container: &Arc, dependency_history: Vec<&'static str>, ) -> Result { Ok(AsyncProvidable::Transient( InjectableType::resolve(di_container, dependency_history).await?, )) } fn do_clone(&self) -> Box { Box::new(self.clone()) } } impl Clone for AsyncTransientTypeProvider where InjectableType: AsyncInjectable, { fn clone(&self) -> Self { Self { injectable_phantom: self.injectable_phantom, } } } pub struct AsyncSingletonProvider where InjectableType: AsyncInjectable, { singleton: ThreadsafeSingletonPtr, } impl AsyncSingletonProvider where InjectableType: AsyncInjectable, { pub fn new(singleton: ThreadsafeSingletonPtr) -> Self { Self { singleton } } } #[async_trait] impl IAsyncProvider for AsyncSingletonProvider where InjectableType: AsyncInjectable, { async fn provide( &self, _di_container: &Arc, _dependency_history: Vec<&'static str>, ) -> Result { Ok(AsyncProvidable::Singleton(self.singleton.clone())) } fn do_clone(&self) -> Box { Box::new(self.clone()) } } impl Clone for AsyncSingletonProvider where InjectableType: AsyncInjectable, { fn clone(&self) -> Self { Self { singleton: self.singleton.clone(), } } } #[derive(Clone, Copy)] pub enum AsyncFactoryVariant { Normal, Default, AsyncDefault, } #[cfg(feature = "factory")] pub struct AsyncFactoryProvider { factory: crate::ptr::ThreadsafeFactoryPtr< dyn crate::interfaces::any_factory::AnyThreadsafeFactory, >, variant: AsyncFactoryVariant, } #[cfg(feature = "factory")] impl AsyncFactoryProvider { pub fn new( factory: crate::ptr::ThreadsafeFactoryPtr< dyn crate::interfaces::any_factory::AnyThreadsafeFactory, >, variant: AsyncFactoryVariant, ) -> Self { Self { factory, variant } } } #[cfg(feature = "factory")] #[async_trait] impl IAsyncProvider for AsyncFactoryProvider { async fn provide( &self, _di_container: &Arc, _dependency_history: Vec<&'static str>, ) -> Result { Ok(match self.variant { AsyncFactoryVariant::Normal => AsyncProvidable::Factory(self.factory.clone()), AsyncFactoryVariant::Default => { AsyncProvidable::DefaultFactory(self.factory.clone()) } AsyncFactoryVariant::AsyncDefault => { AsyncProvidable::AsyncDefaultFactory(self.factory.clone()) } }) } fn do_clone(&self) -> Box { Box::new(self.clone()) } } #[cfg(feature = "factory")] impl Clone for AsyncFactoryProvider { fn clone(&self) -> Self { Self { factory: self.factory.clone(), variant: self.variant, } } }