diff options
Diffstat (limited to 'src/di_container/blocking/binding')
| -rw-r--r-- | src/di_container/blocking/binding/builder.rs | 273 | ||||
| -rw-r--r-- | src/di_container/blocking/binding/scope_configurator.rs | 45 | ||||
| -rw-r--r-- | src/di_container/blocking/binding/when_configurator.rs | 46 | 
3 files changed, 174 insertions, 190 deletions
diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index 8e15f0c..e1c1561 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -1,4 +1,6 @@ -//! Binding builder for types inside of a [`DIContainer`]. +//! Binding builder for types inside of a [`IDIContainer`]. +//! +//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer  use std::any::type_name;  use std::marker::PhantomData;  use std::rc::Rc; @@ -6,24 +8,28 @@ use std::rc::Rc;  use crate::di_container::blocking::binding::scope_configurator::BindingScopeConfigurator;  #[cfg(feature = "factory")]  use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator; -use crate::di_container::blocking::DIContainer; +use crate::di_container::blocking::IDIContainer;  use crate::errors::di_container::BindingBuilderError;  use crate::interfaces::injectable::Injectable; -/// Binding builder for type `Interface` inside a [`DIContainer`]. -pub struct BindingBuilder<Interface> +/// Binding builder for type `Interface` inside a [`IDIContainer`]. +/// +/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +pub struct BindingBuilder<Interface, DIContainerType>  where      Interface: 'static + ?Sized, +    DIContainerType: IDIContainer,  { -    di_container: Rc<DIContainer>, +    di_container: Rc<DIContainerType>,      interface_phantom: PhantomData<Interface>,  } -impl<Interface> BindingBuilder<Interface> +impl<Interface, DIContainerType> BindingBuilder<Interface, DIContainerType>  where      Interface: 'static + ?Sized, +    DIContainerType: IDIContainer,  { -    pub(crate) fn new(di_container: Rc<DIContainer>) -> Self +    pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self      {          Self {              di_container, @@ -32,13 +38,13 @@ where      }      /// Creates a binding of type `Interface` to type `Implementation` inside of the -    /// associated [`DIContainer`]. +    /// associated [`IDIContainer`].      ///      /// The scope of the binding is transient. But that can be changed by using the      /// returned [`BindingScopeConfigurator`]      ///      /// # Errors -    /// Will return Err if the associated [`DIContainer`] already have a binding for +    /// Will return Err if the associated [`IDIContainer`] already have a binding for      /// the interface.      ///      /// # Examples @@ -46,6 +52,7 @@ where      /// # use std::error::Error;      /// #      /// # use syrette::{DIContainer, injectable}; +    /// # use syrette::di_container::blocking::IDIContainer;      /// #      /// # trait Foo {}      /// # @@ -70,16 +77,19 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer      pub fn to<Implementation>(          &self, -    ) -> Result<BindingScopeConfigurator<Interface, Implementation>, BindingBuilderError> +    ) -> Result< +        BindingScopeConfigurator<Interface, Implementation, DIContainerType>, +        BindingBuilderError, +    >      where -        Implementation: Injectable, +        Implementation: Injectable<DIContainerType>,      {          { -            let bindings = self.di_container.bindings.borrow(); - -            if bindings.has::<Interface>(None) { +            if self.di_container.has_binding::<Interface>(None) {                  return Err(BindingBuilderError::BindingAlreadyExists(type_name::<                      Interface,                  >( @@ -96,10 +106,10 @@ where      }      /// Creates a binding of factory type `Interface` to a factory inside of the -    /// associated [`DIContainer`]. +    /// associated [`IDIContainer`].      ///      /// # Errors -    /// Will return Err if the associated [`DIContainer`] already have a binding for +    /// Will return Err if the associated [`IDIContainer`] already have a binding for      /// the interface.      ///      /// # Examples @@ -108,6 +118,7 @@ where      /// #      /// # use syrette::{DIContainer, factory};      /// # use syrette::ptr::TransientPtr; +    /// # use syrette::di_container::blocking::IDIContainer;      /// #      /// # trait ICustomerID {}      /// # trait ICustomer {} @@ -158,36 +169,31 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer      #[cfg(feature = "factory")]      #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]      pub fn to_factory<Args, Return, Func>(          &self,          factory_func: &'static Func, -    ) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError> +    ) -> Result<BindingWhenConfigurator<Interface, DIContainerType>, BindingBuilderError>      where          Args: 'static,          Return: 'static + ?Sized,          Interface: Fn<Args, Output = crate::ptr::TransientPtr<Return>>, -        Func: Fn<(std::rc::Rc<DIContainer>,), Output = Box<Interface>>, +        Func: Fn<(std::rc::Rc<DIContainerType>,), Output = Box<Interface>>,      {          use crate::castable_factory::blocking::CastableFactory; -        { -            let bindings = self.di_container.bindings.borrow(); - -            if bindings.has::<Interface>(None) { -                return Err(BindingBuilderError::BindingAlreadyExists(type_name::< -                    Interface, -                >( -                ))); -            } +        if self.di_container.has_binding::<Interface>(None) { +            return Err(BindingBuilderError::BindingAlreadyExists(type_name::< +                Interface, +            >()));          } -        let mut bindings_mut = self.di_container.bindings.borrow_mut(); -          let factory_impl = CastableFactory::new(factory_func); -        bindings_mut.set::<Interface>( +        self.di_container.set_binding::<Interface>(              None,              Box::new(crate::provider::blocking::FactoryProvider::new(                  crate::ptr::FactoryPtr::new(factory_impl), @@ -199,10 +205,10 @@ where      }      /// Creates a binding of type `Interface` to a factory that takes no arguments -    /// inside of the associated [`DIContainer`]. +    /// inside of the associated [`IDIContainer`].      ///      /// # Errors -    /// Will return Err if the associated [`DIContainer`] already have a binding for +    /// Will return Err if the associated [`IDIContainer`] already have a binding for      /// the interface.      ///      /// # Examples @@ -211,6 +217,7 @@ where      /// #      /// # use syrette::{DIContainer, factory};      /// # use syrette::ptr::TransientPtr; +    /// # use syrette::di_container::blocking::IDIContainer;      /// #      /// # trait IBuffer {}      /// # @@ -248,16 +255,18 @@ where      /// # Ok(())      /// # }      /// ``` +    /// +    /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer      #[cfg(feature = "factory")]      #[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]      pub fn to_default_factory<Return, FactoryFunc>(          &self,          factory_func: &'static FactoryFunc, -    ) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError> +    ) -> Result<BindingWhenConfigurator<Interface, DIContainerType>, BindingBuilderError>      where          Return: 'static + ?Sized,          FactoryFunc: Fn< -            (Rc<DIContainer>,), +            (Rc<DIContainerType>,),              Output = crate::ptr::TransientPtr<                  dyn Fn<(), Output = crate::ptr::TransientPtr<Return>>,              >, @@ -265,22 +274,15 @@ where      {          use crate::castable_factory::blocking::CastableFactory; -        { -            let bindings = self.di_container.bindings.borrow(); - -            if bindings.has::<Interface>(None) { -                return Err(BindingBuilderError::BindingAlreadyExists(type_name::< -                    Interface, -                >( -                ))); -            } +        if self.di_container.has_binding::<Interface>(None) { +            return Err(BindingBuilderError::BindingAlreadyExists(type_name::< +                Interface, +            >()));          } -        let mut bindings_mut = self.di_container.bindings.borrow_mut(); -          let factory_impl = CastableFactory::new(factory_func); -        bindings_mut.set::<Interface>( +        self.di_container.set_binding::<Interface>(              None,              Box::new(crate::provider::blocking::FactoryProvider::new(                  crate::ptr::FactoryPtr::new(factory_impl), @@ -297,92 +299,34 @@ mod tests  {      use std::error::Error; +    use mockall::predicate::eq; +      use super::*; -    use crate::ptr::TransientPtr; -    use crate::test_utils::subjects; +    use crate::test_utils::{mocks, subjects};      #[test]      fn can_bind_to() -> Result<(), Box<dyn Error>>      { -        let mut di_container = DIContainer::new(); +        let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); -        assert_eq!(di_container.bindings.borrow().count(), 0); +        mock_di_container +            .expect_has_binding::<dyn subjects::INumber>() +            .with(eq(None)) +            .return_once(|_name| false) +            .once(); -        di_container -            .bind::<dyn subjects::IUserManager>() -            .to::<subjects::UserManager>()?; +        mock_di_container +            .expect_set_binding::<dyn subjects::INumber>() +            .withf(|name, _provider| name.is_none()) +            .return_once(|_name, _provider| ()) +            .once(); -        assert_eq!(di_container.bindings.borrow().count(), 1); +        let binding_builder = BindingBuilder::< +            dyn subjects::INumber, +            mocks::blocking_di_container::MockDIContainer, +        >::new(Rc::new(mock_di_container)); -        Ok(()) -    } - -    #[test] -    fn can_bind_to_transient() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = DIContainer::new(); - -        assert_eq!(di_container.bindings.borrow().count(), 0); - -        di_container -            .bind::<dyn subjects::IUserManager>() -            .to::<subjects::UserManager>()? -            .in_transient_scope(); - -        assert_eq!(di_container.bindings.borrow().count(), 1); - -        Ok(()) -    } - -    #[test] -    fn can_bind_to_transient_when_named() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = DIContainer::new(); - -        assert_eq!(di_container.bindings.borrow().count(), 0); - -        di_container -            .bind::<dyn subjects::IUserManager>() -            .to::<subjects::UserManager>()? -            .in_transient_scope() -            .when_named("regular")?; - -        assert_eq!(di_container.bindings.borrow().count(), 1); - -        Ok(()) -    } - -    #[test] -    fn can_bind_to_singleton() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = DIContainer::new(); - -        assert_eq!(di_container.bindings.borrow().count(), 0); - -        di_container -            .bind::<dyn subjects::IUserManager>() -            .to::<subjects::UserManager>()? -            .in_singleton_scope()?; - -        assert_eq!(di_container.bindings.borrow().count(), 1); - -        Ok(()) -    } - -    #[test] -    fn can_bind_to_singleton_when_named() -> Result<(), Box<dyn Error>> -    { -        let mut di_container = DIContainer::new(); - -        assert_eq!(di_container.bindings.borrow().count(), 0); - -        di_container -            .bind::<dyn subjects::IUserManager>() -            .to::<subjects::UserManager>()? -            .in_singleton_scope()? -            .when_named("cool")?; - -        assert_eq!(di_container.bindings.borrow().count(), 1); +        binding_builder.to::<subjects::Number>()?;          Ok(())      } @@ -393,57 +337,80 @@ mod tests      {          use crate as syrette;          use crate::factory; +        use crate::ptr::TransientPtr;          #[factory] -        type IUserManagerFactory = dyn Fn() -> dyn subjects::IUserManager; +        type IUserManagerFactory = dyn Fn(i32, String) -> dyn subjects::IUserManager; -        let mut di_container = DIContainer::new(); +        let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); -        assert_eq!(di_container.bindings.borrow().count(), 0); +        mock_di_container +            .expect_has_binding::<IUserManagerFactory>() +            .with(eq(None)) +            .return_once(|_name| false) +            .once(); -        di_container -            .bind::<IUserManagerFactory>() -            .to_factory(&|_| { -                Box::new(move || { -                    let user_manager: TransientPtr<dyn subjects::IUserManager> = -                        TransientPtr::new(subjects::UserManager::new()); +        mock_di_container +            .expect_set_binding::<IUserManagerFactory>() +            .withf(|name, _provider| name.is_none()) +            .return_once(|_name, _provider| ()) +            .once(); -                    user_manager -                }) -            })?; +        let binding_builder = BindingBuilder::< +            IUserManagerFactory, +            mocks::blocking_di_container::MockDIContainer, +        >::new(Rc::new(mock_di_container)); -        assert_eq!(di_container.bindings.borrow().count(), 1); +        binding_builder.to_factory(&|_| { +            Box::new(move |_num, _text| { +                let user_manager: TransientPtr<dyn subjects::IUserManager> = +                    TransientPtr::new(subjects::UserManager::new()); + +                user_manager +            }) +        })?;          Ok(())      }      #[test]      #[cfg(feature = "factory")] -    fn can_bind_to_factory_when_named() -> Result<(), Box<dyn Error>> +    fn can_bind_to_default_factory() -> Result<(), Box<dyn Error>>      { +        use syrette_macros::declare_default_factory; +          use crate as syrette; -        use crate::factory; +        use crate::ptr::TransientPtr; -        #[factory] -        type IUserManagerFactory = dyn Fn() -> dyn subjects::IUserManager; +        declare_default_factory!(dyn subjects::IUserManager); + +        let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); -        let mut di_container = DIContainer::new(); +        mock_di_container +            .expect_has_binding::<dyn subjects::IUserManager>() +            .with(eq(None)) +            .return_once(|_name| false) +            .once(); -        assert_eq!(di_container.bindings.borrow().count(), 0); +        mock_di_container +            .expect_set_binding::<dyn subjects::IUserManager>() +            .withf(|name, _provider| name.is_none()) +            .return_once(|_name, _provider| ()) +            .once(); -        di_container -            .bind::<IUserManagerFactory>() -            .to_factory(&|_| { -                Box::new(move || { -                    let user_manager: TransientPtr<dyn subjects::IUserManager> = -                        TransientPtr::new(subjects::UserManager::new()); +        let binding_builder = BindingBuilder::< +            dyn subjects::IUserManager, +            mocks::blocking_di_container::MockDIContainer, +        >::new(Rc::new(mock_di_container)); -                    user_manager -                }) -            })? -            .when_named("awesome")?; +        binding_builder.to_default_factory(&|_| { +            Box::new(move || { +                let user_manager: TransientPtr<dyn subjects::IUserManager> = +                    TransientPtr::new(subjects::UserManager::new()); -        assert_eq!(di_container.bindings.borrow().count(), 1); +                user_manager +            }) +        })?;          Ok(())      } diff --git a/src/di_container/blocking/binding/scope_configurator.rs b/src/di_container/blocking/binding/scope_configurator.rs index 09897b6..5553415 100644 --- a/src/di_container/blocking/binding/scope_configurator.rs +++ b/src/di_container/blocking/binding/scope_configurator.rs @@ -1,31 +1,38 @@ -//! Scope configurator for a binding for types inside of a [`DIContainer`]. +//! Scope configurator for a binding for types inside of a [`IDIContainer`]. +//! +//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer  use std::marker::PhantomData;  use std::rc::Rc;  use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator; -use crate::di_container::blocking::DIContainer; +use crate::di_container::blocking::IDIContainer;  use crate::errors::di_container::BindingScopeConfiguratorError;  use crate::interfaces::injectable::Injectable;  use crate::provider::blocking::{SingletonProvider, TransientTypeProvider};  use crate::ptr::SingletonPtr; -/// Scope configurator for a binding for type 'Interface' inside a [`DIContainer`]. -pub struct BindingScopeConfigurator<Interface, Implementation> +/// Scope configurator for a binding for type 'Interface' inside a [`IDIContainer`]. +/// +/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +pub struct BindingScopeConfigurator<Interface, Implementation, DIContainerType>  where      Interface: 'static + ?Sized, -    Implementation: Injectable, +    Implementation: Injectable<DIContainerType>, +    DIContainerType: IDIContainer,  { -    di_container: Rc<DIContainer>, +    di_container: Rc<DIContainerType>,      interface_phantom: PhantomData<Interface>,      implementation_phantom: PhantomData<Implementation>,  } -impl<Interface, Implementation> BindingScopeConfigurator<Interface, Implementation> +impl<Interface, Implementation, DIContainerType> +    BindingScopeConfigurator<Interface, Implementation, DIContainerType>  where      Interface: 'static + ?Sized, -    Implementation: Injectable, +    Implementation: Injectable<DIContainerType>, +    DIContainerType: IDIContainer,  { -    pub(crate) fn new(di_container: Rc<DIContainer>) -> Self +    pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self      {          Self {              di_container, @@ -38,13 +45,13 @@ where      ///      /// This is the default.      #[allow(clippy::must_use_candidate)] -    pub fn in_transient_scope(&self) -> BindingWhenConfigurator<Interface> +    pub fn in_transient_scope( +        &self, +    ) -> BindingWhenConfigurator<Interface, DIContainerType>      { -        let mut bindings_mut = self.di_container.bindings.borrow_mut(); - -        bindings_mut.set::<Interface>( +        self.di_container.set_binding::<Interface>(              None, -            Box::new(TransientTypeProvider::<Implementation>::new()), +            Box::new(TransientTypeProvider::<Implementation, DIContainerType>::new()),          );          BindingWhenConfigurator::new(self.di_container.clone()) @@ -56,16 +63,18 @@ where      /// Will return Err if resolving the implementation fails.      pub fn in_singleton_scope(          &self, -    ) -> Result<BindingWhenConfigurator<Interface>, BindingScopeConfiguratorError> +    ) -> Result< +        BindingWhenConfigurator<Interface, DIContainerType>, +        BindingScopeConfiguratorError, +    >      {          let singleton: SingletonPtr<Implementation> = SingletonPtr::from(              Implementation::resolve(&self.di_container, Vec::new())                  .map_err(BindingScopeConfiguratorError::SingletonResolveFailed)?,          ); -        let mut bindings_mut = self.di_container.bindings.borrow_mut(); - -        bindings_mut.set::<Interface>(None, Box::new(SingletonProvider::new(singleton))); +        self.di_container +            .set_binding::<Interface>(None, Box::new(SingletonProvider::new(singleton)));          Ok(BindingWhenConfigurator::new(self.di_container.clone()))      } diff --git a/src/di_container/blocking/binding/when_configurator.rs b/src/di_container/blocking/binding/when_configurator.rs index 9cd9bb6..5b9a8c0 100644 --- a/src/di_container/blocking/binding/when_configurator.rs +++ b/src/di_container/blocking/binding/when_configurator.rs @@ -1,25 +1,31 @@ -//! When configurator for a binding for types inside of a [`DIContainer`]. +//! When configurator for a binding for types inside of a [`IDIContainer`]. +//! +//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer  use std::any::type_name;  use std::marker::PhantomData;  use std::rc::Rc; -use crate::di_container::blocking::DIContainer; +use crate::di_container::blocking::IDIContainer;  use crate::errors::di_container::BindingWhenConfiguratorError; -/// When configurator for a binding for type 'Interface' inside a [`DIContainer`]. -pub struct BindingWhenConfigurator<Interface> +/// When configurator for a binding for type 'Interface' inside a [`IDIContainer`]. +/// +/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +pub struct BindingWhenConfigurator<Interface, DIContainerType>  where      Interface: 'static + ?Sized, +    DIContainerType: IDIContainer,  { -    di_container: Rc<DIContainer>, +    di_container: Rc<DIContainerType>,      interface_phantom: PhantomData<Interface>,  } -impl<Interface> BindingWhenConfigurator<Interface> +impl<Interface, DIContainerType> BindingWhenConfigurator<Interface, DIContainerType>  where      Interface: 'static + ?Sized, +    DIContainerType: IDIContainer,  { -    pub(crate) fn new(di_container: Rc<DIContainer>) -> Self +    pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self      {          Self {              di_container, @@ -36,19 +42,21 @@ where          name: &'static str,      ) -> Result<(), BindingWhenConfiguratorError>      { -        let mut bindings_mut = self.di_container.bindings.borrow_mut(); +        let binding = self +            .di_container +            .remove_binding::<Interface>(None) +            .map_or_else( +                || { +                    Err(BindingWhenConfiguratorError::BindingNotFound(type_name::< +                        Interface, +                    >( +                    ))) +                }, +                Ok, +            )?; -        let binding = bindings_mut.remove::<Interface>(None).map_or_else( -            || { -                Err(BindingWhenConfiguratorError::BindingNotFound(type_name::< -                    Interface, -                >( -                ))) -            }, -            Ok, -        )?; - -        bindings_mut.set::<Interface>(Some(name), binding); +        self.di_container +            .set_binding::<Interface>(Some(name), binding);          Ok(())      }  | 
