diff options
Diffstat (limited to 'src/di_container/asynchronous')
| -rw-r--r-- | src/di_container/asynchronous/binding/builder.rs | 355 | ||||
| -rw-r--r-- | src/di_container/asynchronous/binding/scope_configurator.rs | 58 | ||||
| -rw-r--r-- | src/di_container/asynchronous/binding/when_configurator.rs | 46 | ||||
| -rw-r--r-- | src/di_container/asynchronous/mod.rs | 217 | ||||
| -rw-r--r-- | src/di_container/asynchronous/prelude.rs | 3 | 
5 files changed, 364 insertions, 315 deletions
diff --git a/src/di_container/asynchronous/binding/builder.rs b/src/di_container/asynchronous/binding/builder.rs index 6daba30..d9ad0e6 100644 --- a/src/di_container/asynchronous/binding/builder.rs +++ b/src/di_container/asynchronous/binding/builder.rs @@ -1,4 +1,6 @@ -//! Binding builder for types inside of a [`AsyncDIContainer`]. +//! Binding builder for types inside of a [`IAsyncDIContainer`]. +//! +//! [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer  use std::any::type_name;  use std::marker::PhantomData;  use std::sync::Arc; @@ -6,29 +8,33 @@ use std::sync::Arc;  use crate::di_container::asynchronous::binding::scope_configurator::AsyncBindingScopeConfigurator;  #[cfg(feature = "factory")]  use crate::di_container::asynchronous::binding::when_configurator::AsyncBindingWhenConfigurator; +use crate::di_container::asynchronous::IAsyncDIContainer;  use crate::errors::async_di_container::AsyncBindingBuilderError;  use crate::interfaces::async_injectable::AsyncInjectable; -use crate::AsyncDIContainer;  /// Alias for a threadsafe boxed function.  #[cfg(feature = "factory")]  #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]  pub type BoxFn<Args, Return> = Box<(dyn Fn<Args, Output = Return> + Send + Sync)>; -/// Binding builder for type `Interface` inside a [`AsyncDIContainer`]. -pub struct AsyncBindingBuilder<Interface> +/// Binding builder for type `Interface` inside a [`IAsyncDIContainer`]. +/// +/// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer +pub struct AsyncBindingBuilder<Interface, DIContainerType>  where      Interface: 'static + ?Sized + Send + Sync, +    DIContainerType: IAsyncDIContainer,  { -    di_container: Arc<AsyncDIContainer>, +    di_container: Arc<DIContainerType>,      interface_phantom: PhantomData<Interface>,  } -impl<Interface> AsyncBindingBuilder<Interface> +impl<Interface, DIContainerType> AsyncBindingBuilder<Interface, DIContainerType>  where      Interface: 'static + ?Sized + Send + Sync, +    DIContainerType: IAsyncDIContainer,  { -    pub(crate) fn new(di_container: Arc<AsyncDIContainer>) -> Self +    pub(crate) fn new(di_container: Arc<DIContainerType>) -> Self      {          Self {              di_container, @@ -37,20 +43,21 @@ where      }      /// Creates a binding of type `Interface` to type `Implementation` inside of the -    /// associated [`AsyncDIContainer`]. +    /// associated [`IAsyncDIContainer`].      ///      /// The scope of the binding is transient. But that can be changed by using the      /// returned [`AsyncBindingScopeConfigurator`]      ///      /// # Errors -    /// Will return Err if the associated [`AsyncDIContainer`] already have a binding for +    /// Will return Err if the associated [`IAsyncDIContainer`] already have a binding for      /// the interface.      ///      /// # Examples      /// ```      /// # use std::error::Error;      /// # -    /// # use syrette::{AsyncDIContainer, injectable}; +    /// # use syrette::injectable; +    /// # use syrette::di_container::asynchronous::prelude::*;      /// #      /// # trait Foo: Send + Sync {}      /// # @@ -76,24 +83,22 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer      pub async fn to<Implementation>(          &self,      ) -> Result< -        AsyncBindingScopeConfigurator<Interface, Implementation>, +        AsyncBindingScopeConfigurator<Interface, Implementation, DIContainerType>,          AsyncBindingBuilderError,      >      where -        Implementation: AsyncInjectable, +        Implementation: AsyncInjectable<DIContainerType>,      { -        { -            let bindings_lock = self.di_container.bindings.lock().await; - -            if bindings_lock.has::<Interface>(None) { -                return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::< -                    Interface, -                >( -                ))); -            } +        if self.di_container.has_binding::<Interface>(None).await { +            return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::< +                Interface, +            >( +            )));          }          let binding_scope_configurator = @@ -105,17 +110,18 @@ where      }      /// Creates a binding of factory type `Interface` to a factory inside of the -    /// associated [`AsyncDIContainer`]. +    /// associated [`IAsyncDIContainer`].      ///      /// # Errors -    /// Will return Err if the associated [`AsyncDIContainer`] already have a binding +    /// Will return Err if the associated [`IAsyncDIContainer`] already have a binding      /// for the interface.      ///      /// # Examples      /// ```      /// # use std::error::Error;      /// # -    /// # use syrette::{AsyncDIContainer, factory}; +    /// # use syrette::{factory}; +    /// # use syrette::di_container::asynchronous::prelude::*;      /// # use syrette::ptr::TransientPtr;      /// #      /// # trait Foo: Send + Sync {} @@ -150,25 +156,28 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer      #[cfg(feature = "factory")]      #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]      pub async fn to_factory<Args, Return, FactoryFunc>(          &self,          factory_func: &'static FactoryFunc, -    ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError> +    ) -> Result< +        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingBuilderError, +    >      where          Args: 'static,          Return: 'static + ?Sized,          Interface: Fn<Args, Output = Return> + Send + Sync,          FactoryFunc: -            Fn<(Arc<AsyncDIContainer>,), Output = BoxFn<Args, Return>> + Send + Sync, +            Fn<(Arc<DIContainerType>,), Output = BoxFn<Args, Return>> + Send + Sync,      {          use crate::castable_factory::threadsafe::ThreadsafeCastableFactory;          use crate::provider::r#async::AsyncFactoryVariant; -        let mut bindings_lock = self.di_container.bindings.lock().await; - -        if bindings_lock.has::<Interface>(None) { +        if self.di_container.has_binding::<Interface>(None).await {              return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::<                  Interface,              >( @@ -177,22 +186,24 @@ where          let factory_impl = ThreadsafeCastableFactory::new(factory_func); -        bindings_lock.set::<Interface>( -            None, -            Box::new(crate::provider::r#async::AsyncFactoryProvider::new( -                crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), -                AsyncFactoryVariant::Normal, -            )), -        ); +        self.di_container +            .set_binding::<Interface>( +                None, +                Box::new(crate::provider::r#async::AsyncFactoryProvider::new( +                    crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), +                    AsyncFactoryVariant::Normal, +                )), +            ) +            .await;          Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))      }      /// Creates a binding of factory type `Interface` to a async factory inside of the -    /// associated [`AsyncDIContainer`]. +    /// associated [`IAsyncDIContainer`].      ///      /// # Errors -    /// Will return Err if the associated [`AsyncDIContainer`] already have a binding +    /// Will return Err if the associated [`IAsyncDIContainer`] already have a binding      /// for the interface.      ///      /// # Examples @@ -200,7 +211,8 @@ where      /// # use std::error::Error;      /// # use std::time::Duration;      /// # -    /// # use syrette::{AsyncDIContainer, factory, async_closure}; +    /// # use syrette::{factory, async_closure}; +    /// # use syrette::di_container::asynchronous::prelude::*;      /// # use syrette::ptr::TransientPtr;      /// #      /// # trait Foo: Send + Sync {} @@ -237,19 +249,24 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer      #[cfg(feature = "factory")]      #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]      pub async fn to_async_factory<Args, Return, FactoryFunc>(          &self,          factory_func: &'static FactoryFunc, -    ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError> +    ) -> Result< +        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingBuilderError, +    >      where          Args: 'static,          Return: 'static + ?Sized,          Interface:              Fn<Args, Output = crate::future::BoxFuture<'static, Return>> + Send + Sync,          FactoryFunc: Fn< -                (Arc<AsyncDIContainer>,), +                (Arc<DIContainerType>,),                  Output = BoxFn<Args, crate::future::BoxFuture<'static, Return>>,              > + Send              + Sync, @@ -257,9 +274,7 @@ where          use crate::castable_factory::threadsafe::ThreadsafeCastableFactory;          use crate::provider::r#async::AsyncFactoryVariant; -        let mut bindings_lock = self.di_container.bindings.lock().await; - -        if bindings_lock.has::<Interface>(None) { +        if self.di_container.has_binding::<Interface>(None).await {              return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::<                  Interface,              >( @@ -268,29 +283,31 @@ where          let factory_impl = ThreadsafeCastableFactory::new(factory_func); -        bindings_lock.set::<Interface>( -            None, -            Box::new(crate::provider::r#async::AsyncFactoryProvider::new( -                crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), -                AsyncFactoryVariant::Normal, -            )), -        ); +        self.di_container +            .set_binding::<Interface>( +                None, +                Box::new(crate::provider::r#async::AsyncFactoryProvider::new( +                    crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), +                    AsyncFactoryVariant::Normal, +                )), +            ) +            .await;          Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))      }      /// Creates a binding of type `Interface` to a factory that takes no arguments -    /// inside of the associated [`AsyncDIContainer`]. +    /// inside of the associated [`IAsyncDIContainer`].      ///      /// # Errors -    /// Will return Err if the associated [`AsyncDIContainer`] already have a binding +    /// Will return Err if the associated [`IAsyncDIContainer`] already have a binding      /// for the interface.      ///      /// # Examples      /// ```      /// # use std::error::Error;      /// # -    /// # use syrette::AsyncDIContainer; +    /// # use syrette::di_container::asynchronous::prelude::*;      /// # use syrette::ptr::TransientPtr;      /// #      /// # trait Foo: Send + Sync {} @@ -325,16 +342,21 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer      #[cfg(feature = "factory")]      #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]      pub async fn to_default_factory<Return, FactoryFunc>(          &self,          factory_func: &'static FactoryFunc, -    ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError> +    ) -> Result< +        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingBuilderError, +    >      where          Return: 'static + ?Sized,          FactoryFunc: Fn< -                (Arc<AsyncDIContainer>,), +                (Arc<DIContainerType>,),                  Output = BoxFn<(), crate::ptr::TransientPtr<Return>>,              > + Send              + Sync, @@ -342,9 +364,7 @@ where          use crate::castable_factory::threadsafe::ThreadsafeCastableFactory;          use crate::provider::r#async::AsyncFactoryVariant; -        let mut bindings_lock = self.di_container.bindings.lock().await; - -        if bindings_lock.has::<Interface>(None) { +        if self.di_container.has_binding::<Interface>(None).await {              return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::<                  Interface,              >( @@ -353,22 +373,24 @@ where          let factory_impl = ThreadsafeCastableFactory::new(factory_func); -        bindings_lock.set::<Interface>( -            None, -            Box::new(crate::provider::r#async::AsyncFactoryProvider::new( -                crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), -                AsyncFactoryVariant::Default, -            )), -        ); +        self.di_container +            .set_binding::<Interface>( +                None, +                Box::new(crate::provider::r#async::AsyncFactoryProvider::new( +                    crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), +                    AsyncFactoryVariant::Default, +                )), +            ) +            .await;          Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))      }      /// Creates a binding of factory type `Interface` to a async factory inside of the -    /// associated [`AsyncDIContainer`]. +    /// associated [`IAsyncDIContainer`].      ///      /// # Errors -    /// Will return Err if the associated [`AsyncDIContainer`] already have a binding +    /// Will return Err if the associated [`IAsyncDIContainer`] already have a binding      /// for the interface.      ///      /// # Examples @@ -376,7 +398,8 @@ where      /// # use std::error::Error;      /// # use std::time::Duration;      /// # -    /// # use syrette::{AsyncDIContainer, async_closure}; +    /// # use syrette::async_closure; +    /// # use syrette::di_container::asynchronous::prelude::*;      /// # use syrette::ptr::TransientPtr;      /// #      /// # trait Foo: Send + Sync {} @@ -413,16 +436,21 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer      #[cfg(feature = "factory")]      #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]      pub async fn to_async_default_factory<Return, FactoryFunc>(          &self,          factory_func: &'static FactoryFunc, -    ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError> +    ) -> Result< +        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingBuilderError, +    >      where          Return: 'static + ?Sized,          FactoryFunc: Fn< -                (Arc<AsyncDIContainer>,), +                (Arc<DIContainerType>,),                  Output = BoxFn<(), crate::future::BoxFuture<'static, Return>>,              > + Send              + Sync, @@ -430,9 +458,7 @@ where          use crate::castable_factory::threadsafe::ThreadsafeCastableFactory;          use crate::provider::r#async::AsyncFactoryVariant; -        let mut bindings_lock = self.di_container.bindings.lock().await; - -        if bindings_lock.has::<Interface>(None) { +        if self.di_container.has_binding::<Interface>(None).await {              return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::<                  Interface,              >( @@ -441,13 +467,15 @@ where          let factory_impl = ThreadsafeCastableFactory::new(factory_func); -        bindings_lock.set::<Interface>( -            None, -            Box::new(crate::provider::r#async::AsyncFactoryProvider::new( -                crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), -                AsyncFactoryVariant::AsyncDefault, -            )), -        ); +        self.di_container +            .set_binding::<Interface>( +                None, +                Box::new(crate::provider::r#async::AsyncFactoryProvider::new( +                    crate::ptr::ThreadsafeFactoryPtr::new(factory_impl), +                    AsyncFactoryVariant::AsyncDefault, +                )), +            ) +            .await;          Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))      } @@ -458,127 +486,40 @@ mod tests  {      use std::error::Error; +    use mockall::predicate::eq; +      use super::*; -    use crate::ptr::TransientPtr; +    use crate::test_utils::mocks::async_di_container::MockAsyncDIContainer;      use crate::test_utils::subjects_async;      #[tokio::test]      async fn can_bind_to() -> Result<(), Box<dyn Error>>      { -        let mut di_container = AsyncDIContainer::new(); +        let mut di_container_mock = MockAsyncDIContainer::new(); -        { -            assert_eq!(di_container.bindings.lock().await.count(), 0); -        } +        di_container_mock +            .expect_has_binding::<dyn subjects_async::IUserManager>() +            .with(eq(None)) +            .return_once(|_name| false) +            .once(); -        di_container -            .bind::<dyn subjects_async::IUserManager>() -            .to::<subjects_async::UserManager>() -            .await?; +        di_container_mock +            .expect_set_binding::<dyn subjects_async::IUserManager>() +            .withf(|name, _provider| name.is_none()) +            .return_once(|_name, _provider| ()) +            .once(); -        { -            assert_eq!(di_container.bindings.lock().await.count(), 1); -        } - -        Ok(()) -    } - -    #[tokio::test] -    async fn can_bind_to_transient() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = AsyncDIContainer::new(); - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 0); -        } +        let binding_builder = AsyncBindingBuilder::< +            dyn subjects_async::IUserManager, +            MockAsyncDIContainer, +        >::new(Arc::new(di_container_mock)); -        di_container -            .bind::<dyn subjects_async::IUserManager>() -            .to::<subjects_async::UserManager>() -            .await? -            .in_transient_scope() -            .await; - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 1); -        } - -        Ok(()) -    } - -    #[tokio::test] -    async fn can_bind_to_transient_when_named() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = AsyncDIContainer::new(); - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 0); -        } - -        di_container -            .bind::<dyn subjects_async::IUserManager>() -            .to::<subjects_async::UserManager>() -            .await? -            .in_transient_scope() -            .await -            .when_named("regular") -            .await?; - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 1); -        } - -        Ok(()) -    } - -    #[tokio::test] -    async fn can_bind_to_singleton() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = AsyncDIContainer::new(); - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 0); -        } - -        di_container -            .bind::<dyn subjects_async::IUserManager>() -            .to::<subjects_async::UserManager>() -            .await? -            .in_singleton_scope() -            .await?; - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 1); -        } - -        Ok(()) -    } - -    #[tokio::test] -    async fn can_bind_to_singleton_when_named() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = AsyncDIContainer::new(); - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 0); -        } - -        di_container -            .bind::<dyn subjects_async::IUserManager>() -            .to::<subjects_async::UserManager>() -            .await? -            .in_singleton_scope() -            .await? -            .when_named("cool") -            .await?; - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 1); -        } +        binding_builder.to::<subjects_async::UserManager>().await?;          Ok(())      } +    /*      #[tokio::test]      #[cfg(feature = "factory")]      async fn can_bind_to_factory() -> Result<(), Box<dyn Error>> @@ -613,41 +554,5 @@ mod tests          Ok(())      } - -    #[tokio::test] -    #[cfg(feature = "factory")] -    async fn can_bind_to_factory_when_named() -> Result<(), Box<dyn Error>> -    { -        use crate as syrette; -        use crate::factory; - -        #[factory(threadsafe = true)] -        type IUserManagerFactory = dyn Fn() -> dyn subjects_async::IUserManager; - -        let mut di_container = AsyncDIContainer::new(); - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 0); -        } - -        di_container -            .bind::<IUserManagerFactory>() -            .to_factory(&|_| { -                Box::new(|| { -                    let user_manager: TransientPtr<dyn subjects_async::IUserManager> = -                        TransientPtr::new(subjects_async::UserManager::new()); - -                    user_manager -                }) -            }) -            .await? -            .when_named("awesome") -            .await?; - -        { -            assert_eq!(di_container.bindings.lock().await.count(), 1); -        } - -        Ok(()) -    } +    */  } diff --git a/src/di_container/asynchronous/binding/scope_configurator.rs b/src/di_container/asynchronous/binding/scope_configurator.rs index 2b0f0b3..fd42fea 100644 --- a/src/di_container/asynchronous/binding/scope_configurator.rs +++ b/src/di_container/asynchronous/binding/scope_configurator.rs @@ -1,31 +1,38 @@ -//! Scope configurator for a binding for types inside of a [`AsyncDIContainer`]. +//! Scope configurator for a binding for types inside of a [`IAsyncDIContainer`]. +//! +//! [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer  use std::marker::PhantomData;  use std::sync::Arc;  use crate::di_container::asynchronous::binding::when_configurator::AsyncBindingWhenConfigurator; +use crate::di_container::asynchronous::IAsyncDIContainer;  use crate::errors::async_di_container::AsyncBindingScopeConfiguratorError;  use crate::interfaces::async_injectable::AsyncInjectable;  use crate::provider::r#async::{AsyncSingletonProvider, AsyncTransientTypeProvider};  use crate::ptr::ThreadsafeSingletonPtr; -use crate::AsyncDIContainer; -/// Scope configurator for a binding for type 'Interface' inside a [`AsyncDIContainer`]. -pub struct AsyncBindingScopeConfigurator<Interface, Implementation> +/// Scope configurator for a binding for type 'Interface' inside a [`IAsyncDIContainer`]. +/// +/// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer +pub struct AsyncBindingScopeConfigurator<Interface, Implementation, DIContainerType>  where      Interface: 'static + ?Sized + Send + Sync, -    Implementation: AsyncInjectable, +    Implementation: AsyncInjectable<DIContainerType>, +    DIContainerType: IAsyncDIContainer,  { -    di_container: Arc<AsyncDIContainer>, +    di_container: Arc<DIContainerType>,      interface_phantom: PhantomData<Interface>,      implementation_phantom: PhantomData<Implementation>,  } -impl<Interface, Implementation> AsyncBindingScopeConfigurator<Interface, Implementation> +impl<Interface, Implementation, DIContainerType> +    AsyncBindingScopeConfigurator<Interface, Implementation, DIContainerType>  where      Interface: 'static + ?Sized + Send + Sync, -    Implementation: AsyncInjectable, +    Implementation: AsyncInjectable<DIContainerType>, +    DIContainerType: IAsyncDIContainer,  { -    pub(crate) fn new(di_container: Arc<AsyncDIContainer>) -> Self +    pub(crate) fn new(di_container: Arc<DIContainerType>) -> Self      {          Self {              di_container, @@ -37,14 +44,18 @@ where      /// Configures the binding to be in a transient scope.      ///      /// This is the default. -    pub async fn in_transient_scope(&self) -> AsyncBindingWhenConfigurator<Interface> +    pub async fn in_transient_scope( +        &self, +    ) -> AsyncBindingWhenConfigurator<Interface, DIContainerType>      { -        let mut bindings_lock = self.di_container.bindings.lock().await; - -        bindings_lock.set::<Interface>( -            None, -            Box::new(AsyncTransientTypeProvider::<Implementation>::new()), -        ); +        self.di_container +            .set_binding::<Interface>( +                None, +                Box::new( +                    AsyncTransientTypeProvider::<Implementation, DIContainerType>::new(), +                ), +            ) +            .await;          AsyncBindingWhenConfigurator::new(self.di_container.clone())      } @@ -55,7 +66,10 @@ where      /// Will return Err if resolving the implementation fails.      pub async fn in_singleton_scope(          &self, -    ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingScopeConfiguratorError> +    ) -> Result< +        AsyncBindingWhenConfigurator<Interface, DIContainerType>, +        AsyncBindingScopeConfiguratorError, +    >      {          let singleton: ThreadsafeSingletonPtr<Implementation> =              ThreadsafeSingletonPtr::from( @@ -66,10 +80,12 @@ where                      )?,              ); -        let mut bindings_lock = self.di_container.bindings.lock().await; - -        bindings_lock -            .set::<Interface>(None, Box::new(AsyncSingletonProvider::new(singleton))); +        self.di_container +            .set_binding::<Interface>( +                None, +                Box::new(AsyncSingletonProvider::new(singleton)), +            ) +            .await;          Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))      } diff --git a/src/di_container/asynchronous/binding/when_configurator.rs b/src/di_container/asynchronous/binding/when_configurator.rs index b245ad8..3175420 100644 --- a/src/di_container/asynchronous/binding/when_configurator.rs +++ b/src/di_container/asynchronous/binding/when_configurator.rs @@ -1,25 +1,31 @@ -//! When configurator for a binding for types inside of a [`AsyncDIContainer`]. +//! When configurator for a binding for types inside of a [`IAsyncDIContainer`]. +//! +//! [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer  use std::any::type_name;  use std::marker::PhantomData;  use std::sync::Arc; +use crate::di_container::asynchronous::IAsyncDIContainer;  use crate::errors::async_di_container::AsyncBindingWhenConfiguratorError; -use crate::AsyncDIContainer; -/// When configurator for a binding for type 'Interface' inside a [`AsyncDIContainer`]. -pub struct AsyncBindingWhenConfigurator<Interface> +/// When configurator for a binding for type 'Interface' inside a [`IAsyncDIContainer`]. +/// +/// [`IAsyncDIContainer`]: crate::di_container::asynchronous::IAsyncDIContainer +pub struct AsyncBindingWhenConfigurator<Interface, DIContainerType>  where      Interface: 'static + ?Sized + Send + Sync, +    DIContainerType: IAsyncDIContainer,  { -    di_container: Arc<AsyncDIContainer>, +    di_container: Arc<DIContainerType>,      interface_phantom: PhantomData<Interface>,  } -impl<Interface> AsyncBindingWhenConfigurator<Interface> +impl<Interface, DIContainerType> AsyncBindingWhenConfigurator<Interface, DIContainerType>  where      Interface: 'static + ?Sized + Send + Sync, +    DIContainerType: IAsyncDIContainer,  { -    pub(crate) fn new(di_container: Arc<AsyncDIContainer>) -> Self +    pub(crate) fn new(di_container: Arc<DIContainerType>) -> Self      {          Self {              di_container, @@ -36,18 +42,22 @@ where          name: &'static str,      ) -> Result<(), AsyncBindingWhenConfiguratorError>      { -        let mut bindings_lock = self.di_container.bindings.lock().await; +        let binding = self +            .di_container +            .remove_binding::<Interface>(None) +            .await +            .map_or_else( +                || { +                    Err(AsyncBindingWhenConfiguratorError::BindingNotFound( +                        type_name::<Interface>(), +                    )) +                }, +                Ok, +            )?; -        let binding = bindings_lock.remove::<Interface>(None).map_or_else( -            || { -                Err(AsyncBindingWhenConfiguratorError::BindingNotFound( -                    type_name::<Interface>(), -                )) -            }, -            Ok, -        )?; - -        bindings_lock.set::<Interface>(Some(name), binding); +        self.di_container +            .set_binding::<Interface>(Some(name), binding) +            .await;          Ok(())      } diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs index b6653a5..14e6abe 100644 --- a/src/di_container/asynchronous/mod.rs +++ b/src/di_container/asynchronous/mod.rs @@ -5,7 +5,8 @@  //! use std::collections::HashMap;  //! use std::error::Error;  //! -//! use syrette::{injectable, AsyncDIContainer}; +//! use syrette::di_container::asynchronous::prelude::*; +//! use syrette::injectable;  //!  //! trait IDatabaseService: Send + Sync  //! { @@ -53,6 +54,7 @@  use std::any::type_name;  use std::sync::Arc; +use async_trait::async_trait;  use tokio::sync::Mutex;  use crate::di_container::asynchronous::binding::builder::AsyncBindingBuilder; @@ -65,11 +67,64 @@ use crate::provider::r#async::{AsyncProvidable, IAsyncProvider};  use crate::ptr::{SomeThreadsafePtr, TransientPtr};  pub mod binding; +pub mod prelude; + +/// Dependency injection container interface. +#[async_trait] +pub trait IAsyncDIContainer: +    Sized + 'static + Send + Sync + details::DIContainerInternals +{ +    /// Returns a new [`AsyncBindingBuilder`] for the given interface. +    #[must_use] +    fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface, Self> +    where +        Interface: 'static + ?Sized + Send + Sync; + +    /// Returns the type bound with `Interface`. +    /// +    /// # Errors +    /// Will return `Err` if: +    /// - No binding for `Interface` exists +    /// - Resolving the binding for `Interface` fails +    /// - Casting the binding for `Interface` fails +    fn get<'a, 'b, Interface>( +        self: &'a Arc<Self>, +    ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>> +    where +        Interface: 'static + 'b + ?Sized + Send + Sync, +        'a: 'b, +        Self: 'b; + +    /// Returns the type bound with `Interface` and the specified name. +    /// +    /// # Errors +    /// Will return `Err` if: +    /// - No binding for `Interface` with name `name` exists +    /// - Resolving the binding for `Interface` fails +    /// - Casting the binding for `Interface` fails +    fn get_named<'a, 'b, Interface>( +        self: &'a Arc<Self>, +        name: &'static str, +    ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>> +    where +        Interface: 'static + 'b + ?Sized + Send + Sync, +        'a: 'b, +        Self: 'b; + +    #[doc(hidden)] +    async fn get_bound<Interface>( +        self: &Arc<Self>, +        dependency_history: Vec<&'static str>, +        name: Option<&'static str>, +    ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError> +    where +        Interface: 'static + ?Sized + Send + Sync; +}  /// Dependency injection container.  pub struct AsyncDIContainer  { -    bindings: Mutex<DIContainerBindingMap<dyn IAsyncProvider>>, +    bindings: Mutex<DIContainerBindingMap<dyn IAsyncProvider<Self>>>,  }  impl AsyncDIContainer @@ -82,51 +137,43 @@ impl AsyncDIContainer              bindings: Mutex::new(DIContainerBindingMap::new()),          })      } +} -    /// Returns a new [`AsyncBindingBuilder`] for the given interface. +#[async_trait] +impl IAsyncDIContainer for AsyncDIContainer +{      #[must_use] -    pub fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface> +    fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface, Self>      where          Interface: 'static + ?Sized + Send + Sync,      { -        AsyncBindingBuilder::<Interface>::new(self.clone()) +        AsyncBindingBuilder::new(self.clone())      } -    /// Returns the type bound with `Interface`. -    /// -    /// # Errors -    /// Will return `Err` if: -    /// - No binding for `Interface` exists -    /// - Resolving the binding for `Interface` fails -    /// - Casting the binding for `Interface` fails -    pub async fn get<Interface>( -        self: &Arc<Self>, -    ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError> +    fn get<'a, 'b, Interface>( +        self: &'a Arc<Self>, +    ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>>      where -        Interface: 'static + ?Sized + Send + Sync, +        Interface: 'static + 'b + ?Sized + Send + Sync, +        'a: 'b, +        Self: 'b,      { -        self.get_bound::<Interface>(Vec::new(), None).await +        Box::pin(async { self.get_bound::<Interface>(Vec::new(), None).await })      } -    /// Returns the type bound with `Interface` and the specified name. -    /// -    /// # Errors -    /// Will return `Err` if: -    /// - No binding for `Interface` with name `name` exists -    /// - Resolving the binding for `Interface` fails -    /// - Casting the binding for `Interface` fails -    pub async fn get_named<Interface>( -        self: &Arc<Self>, +    fn get_named<'a, 'b, Interface>( +        self: &'a Arc<Self>,          name: &'static str, -    ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError> +    ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>>      where -        Interface: 'static + ?Sized + Send + Sync, +        Interface: 'static + 'b + ?Sized + Send + Sync, +        'a: 'b, +        Self: 'b,      { -        self.get_bound::<Interface>(Vec::new(), Some(name)).await +        Box::pin(async { self.get_bound::<Interface>(Vec::new(), Some(name)).await })      } -    #[doc(hidden)] -    pub async fn get_bound<Interface>( +    async fn get_bound<Interface>(          self: &Arc<Self>,          dependency_history: Vec<&'static str>,          name: Option<&'static str>, @@ -140,10 +187,44 @@ impl AsyncDIContainer          self.handle_binding_providable(binding_providable).await      } +} + +#[async_trait] +impl details::DIContainerInternals for AsyncDIContainer +{ +    async fn has_binding<Interface>(self: &Arc<Self>, name: Option<&'static str>) -> bool +    where +        Interface: ?Sized + 'static, +    { +        self.bindings.lock().await.has::<Interface>(name) +    } + +    async fn set_binding<Interface>( +        self: &Arc<Self>, +        name: Option<&'static str>, +        provider: Box<dyn IAsyncProvider<Self>>, +    ) where +        Interface: 'static + ?Sized, +    { +        self.bindings.lock().await.set::<Interface>(name, provider); +    } +    async fn remove_binding<Interface>( +        self: &Arc<Self>, +        name: Option<&'static str>, +    ) -> Option<Box<dyn IAsyncProvider<Self>>> +    where +        Interface: 'static + ?Sized, +    { +        self.bindings.lock().await.remove::<Interface>(name) +    } +} + +impl AsyncDIContainer +{      async fn handle_binding_providable<Interface>(          self: &Arc<Self>, -        binding_providable: AsyncProvidable, +        binding_providable: AsyncProvidable<Self>,      ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>      where          Interface: 'static + ?Sized + Send + Sync, @@ -261,7 +342,7 @@ impl AsyncDIContainer          self: &Arc<Self>,          name: Option<&'static str>,          dependency_history: Vec<&'static str>, -    ) -> Result<AsyncProvidable, AsyncDIContainerError> +    ) -> Result<AsyncProvidable<Self>, AsyncDIContainerError>      where          Interface: 'static + ?Sized + Send + Sync,      { @@ -294,6 +375,40 @@ impl AsyncDIContainer      }  } +pub(crate) mod details +{ +    use std::sync::Arc; + +    use async_trait::async_trait; + +    use crate::provider::r#async::IAsyncProvider; + +    #[async_trait] +    pub trait DIContainerInternals +    { +        async fn has_binding<Interface>( +            self: &Arc<Self>, +            name: Option<&'static str>, +        ) -> bool +        where +            Interface: ?Sized + 'static; + +        async fn set_binding<Interface>( +            self: &Arc<Self>, +            name: Option<&'static str>, +            provider: Box<dyn IAsyncProvider<Self>>, +        ) where +            Interface: 'static + ?Sized; + +        async fn remove_binding<Interface>( +            self: &Arc<Self>, +            name: Option<&'static str>, +        ) -> Option<Box<dyn IAsyncProvider<Self>>> +        where +            Interface: 'static + ?Sized; +    } +} +  #[cfg(test)]  mod tests  { @@ -314,15 +429,15 @@ mod tests              Provider {}              #[async_trait] -            impl IAsyncProvider for Provider +            impl IAsyncProvider<AsyncDIContainer> for Provider              {                  async fn provide(                      &self,                      di_container: &Arc<AsyncDIContainer>,                      dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable, InjectableError>; +                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; -                fn do_clone(&self) -> Box<dyn IAsyncProvider>; +                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;              }          } @@ -365,15 +480,15 @@ mod tests              Provider {}              #[async_trait] -            impl IAsyncProvider for Provider +            impl IAsyncProvider<AsyncDIContainer> for Provider              {                  async fn provide(                      &self,                      di_container: &Arc<AsyncDIContainer>,                      dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable, InjectableError>; +                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; -                fn do_clone(&self) -> Box<dyn IAsyncProvider>; +                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;              }          } @@ -419,15 +534,15 @@ mod tests              Provider {}              #[async_trait] -            impl IAsyncProvider for Provider +            impl IAsyncProvider<AsyncDIContainer> for Provider              {                  async fn provide(                      &self,                      di_container: &Arc<AsyncDIContainer>,                      dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable, InjectableError>; +                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; -                fn do_clone(&self) -> Box<dyn IAsyncProvider>; +                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;              }          } @@ -483,15 +598,15 @@ mod tests              Provider {}              #[async_trait] -            impl IAsyncProvider for Provider +            impl IAsyncProvider<AsyncDIContainer> for Provider              {                  async fn provide(                      &self,                      di_container: &Arc<AsyncDIContainer>,                      dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable, InjectableError>; +                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; -                fn do_clone(&self) -> Box<dyn IAsyncProvider>; +                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;              }          } @@ -593,15 +708,15 @@ mod tests              Provider {}              #[async_trait] -            impl IAsyncProvider for Provider +            impl IAsyncProvider<AsyncDIContainer> for Provider              {                  async fn provide(                      &self,                      di_container: &Arc<AsyncDIContainer>,                      dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable, InjectableError>; +                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; -                fn do_clone(&self) -> Box<dyn IAsyncProvider>; +                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;              }          } @@ -704,15 +819,15 @@ mod tests              Provider {}              #[async_trait] -            impl IAsyncProvider for Provider +            impl IAsyncProvider<AsyncDIContainer> for Provider              {                  async fn provide(                      &self,                      di_container: &Arc<AsyncDIContainer>,                      dependency_history: Vec<&'static str>, -                ) -> Result<AsyncProvidable, InjectableError>; +                ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>; -                fn do_clone(&self) -> Box<dyn IAsyncProvider>; +                fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;              }          } diff --git a/src/di_container/asynchronous/prelude.rs b/src/di_container/asynchronous/prelude.rs new file mode 100644 index 0000000..50fc42b --- /dev/null +++ b/src/di_container/asynchronous/prelude.rs @@ -0,0 +1,3 @@ +//! Commonly used types. + +pub use crate::di_container::asynchronous::{AsyncDIContainer, IAsyncDIContainer};  | 
