diff options
-rw-r--r-- | examples/basic/main.rs | 1 | ||||
-rw-r--r-- | examples/factory/main.rs | 2 | ||||
-rw-r--r-- | examples/generics/main.rs | 2 | ||||
-rw-r--r-- | examples/named/main.rs | 1 | ||||
-rw-r--r-- | examples/with-3rd-party/main.rs | 2 | ||||
-rw-r--r-- | macros/src/injectable/implementation.rs | 3 | ||||
-rw-r--r-- | src/di_container/blocking/binding/builder.rs | 92 | ||||
-rw-r--r-- | src/di_container/blocking/binding/scope_configurator.rs | 68 | ||||
-rw-r--r-- | src/di_container/blocking/binding/when_configurator.rs | 35 | ||||
-rw-r--r-- | src/di_container/blocking/mod.rs | 318 | ||||
-rw-r--r-- | src/di_container/blocking/prelude.rs | 2 | ||||
-rw-r--r-- | src/interfaces/injectable.rs | 11 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/provider/blocking.rs | 37 | ||||
-rw-r--r-- | src/test_utils.rs | 124 |
15 files changed, 259 insertions, 440 deletions
diff --git a/examples/basic/main.rs b/examples/basic/main.rs index 7b129e9..dbc9215 100644 --- a/examples/basic/main.rs +++ b/examples/basic/main.rs @@ -11,7 +11,6 @@ mod interfaces; use bootstrap::bootstrap; use interfaces::dog::IDog; use interfaces::human::IHuman; -use syrette::di_container::blocking::prelude::*; fn main() -> Result<(), Box<dyn Error>> { diff --git a/examples/factory/main.rs b/examples/factory/main.rs index d428717..2c18829 100644 --- a/examples/factory/main.rs +++ b/examples/factory/main.rs @@ -9,8 +9,6 @@ mod user_manager; use std::error::Error; -use syrette::di_container::blocking::prelude::*; - use crate::bootstrap::bootstrap; use crate::interfaces::user_manager::IUserManager; diff --git a/examples/generics/main.rs b/examples/generics/main.rs index 7910cad..e54b168 100644 --- a/examples/generics/main.rs +++ b/examples/generics/main.rs @@ -4,8 +4,6 @@ mod printer; use std::error::Error; -use syrette::di_container::blocking::prelude::*; - use crate::bootstrap::bootstrap; use crate::interfaces::printer::IPrinter; diff --git a/examples/named/main.rs b/examples/named/main.rs index e7cccd0..5411a12 100644 --- a/examples/named/main.rs +++ b/examples/named/main.rs @@ -9,7 +9,6 @@ mod ninja; mod shuriken; use anyhow::Result; -use syrette::di_container::blocking::prelude::*; use crate::bootstrap::bootstrap; use crate::interfaces::ninja::INinja; diff --git a/examples/with-3rd-party/main.rs b/examples/with-3rd-party/main.rs index 520038e..e9f8c89 100644 --- a/examples/with-3rd-party/main.rs +++ b/examples/with-3rd-party/main.rs @@ -8,8 +8,6 @@ mod ninja; use std::error::Error; -use syrette::di_container::blocking::prelude::*; - use crate::bootstrap::bootstrap; use crate::interfaces::ninja::INinja; diff --git a/macros/src/injectable/implementation.rs b/macros/src/injectable/implementation.rs index 9e97f45..1efd1fa 100644 --- a/macros/src/injectable/implementation.rs +++ b/macros/src/injectable/implementation.rs @@ -289,7 +289,7 @@ impl<Dep: IDependency> InjectableImpl<Dep> quote! { #maybe_doc_hidden impl #generics syrette::interfaces::injectable::Injectable< - syrette::di_container::blocking::DIContainer, + ::syrette::di_container::blocking::DIContainer > for #self_type { fn resolve( @@ -303,7 +303,6 @@ impl<Dep: IDependency> InjectableImpl<Dep> { use std::any::type_name; - use syrette::di_container::blocking::IDIContainer; use syrette::errors::injectable::InjectableError; let self_type_name = type_name::<#self_type>(); diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index bfc9e4e..64e787e 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -1,6 +1,4 @@ -//! Binding builder for types inside of a [`IDIContainer`]. -//! -//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer +//! Binding builder for types inside of a [`DIContainer`]. use std::any::type_name; use std::marker::PhantomData; use std::rc::Rc; @@ -8,36 +6,32 @@ 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::IDIContainer; use crate::di_container::BindingOptions; use crate::errors::di_container::BindingBuilderError; use crate::interfaces::injectable::Injectable; use crate::util::use_double; use_double!(crate::dependency_history::DependencyHistory); +use_double!(crate::di_container::blocking::DIContainer); -/// Binding builder for type `Interface` inside a [`IDIContainer`]. -/// -/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer +/// Binding builder for type `Interface` inside a [`DIContainer`]. #[must_use = "No binding will be created if you don't use the binding builder"] -pub struct BindingBuilder<Interface, DIContainerType> +pub struct BindingBuilder<Interface> where Interface: 'static + ?Sized, - DIContainerType: IDIContainer, { - di_container: Rc<DIContainerType>, + di_container: Rc<DIContainer>, dependency_history_factory: fn() -> DependencyHistory, interface_phantom: PhantomData<Interface>, } -impl<Interface, DIContainerType> BindingBuilder<Interface, DIContainerType> +impl<Interface> BindingBuilder<Interface> where Interface: 'static + ?Sized, - DIContainerType: IDIContainer, { pub(crate) fn new( - di_container: Rc<DIContainerType>, + di_container: Rc<DIContainer>, dependency_history_factory: fn() -> DependencyHistory, ) -> Self { @@ -49,13 +43,13 @@ where } /// Creates a binding of type `Interface` to type `Implementation` inside of the - /// associated [`IDIContainer`]. + /// associated [`DIContainer`]. /// /// The scope of the binding is transient. But that can be changed by using the /// returned [`BindingScopeConfigurator`] /// /// # Errors - /// Will return Err if the associated [`IDIContainer`] already have a binding for + /// Will return Err if the associated [`DIContainer`] already have a binding for /// the interface. /// /// # Examples @@ -63,7 +57,6 @@ where /// # use std::error::Error; /// # /// # use syrette::{DIContainer, injectable}; - /// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait Foo {} /// # @@ -88,16 +81,11 @@ where /// # Ok(()) /// # } /// ``` - /// - /// [`IDIContainer`]: crate::di_container::blocking::IDIContainer pub fn to<Implementation>( self, - ) -> Result< - BindingScopeConfigurator<Interface, Implementation, DIContainerType>, - BindingBuilderError, - > + ) -> Result<BindingScopeConfigurator<Interface, Implementation>, BindingBuilderError> where - Implementation: Injectable<DIContainerType>, + Implementation: Injectable<DIContainer>, { if self .di_container @@ -119,10 +107,10 @@ where } /// Creates a binding of factory type `Interface` to a factory inside of the - /// associated [`IDIContainer`]. + /// associated [`DIContainer`]. /// /// # Errors - /// Will return Err if the associated [`IDIContainer`] already have a binding for + /// Will return Err if the associated [`DIContainer`] already have a binding for /// the interface. /// /// # Examples @@ -131,7 +119,6 @@ where /// # /// # use syrette::{DIContainer, factory}; /// # use syrette::ptr::TransientPtr; - /// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait ICustomerID {} /// # trait ICustomer {} @@ -182,19 +169,17 @@ 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, DIContainerType>, BindingBuilderError> + ) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError> where Args: std::marker::Tuple + 'static, Return: 'static + ?Sized, Interface: Fn<Args, Output = crate::ptr::TransientPtr<Return>>, - Func: Fn<(std::rc::Rc<DIContainerType>,), Output = Box<Interface>>, + Func: Fn<(std::rc::Rc<DIContainer>,), Output = Box<Interface>>, { use crate::private::castable_factory::blocking::CastableFactory; @@ -221,10 +206,10 @@ where } /// Creates a binding of type `Interface` to a factory that takes no arguments - /// inside of the associated [`IDIContainer`]. + /// inside of the associated [`DIContainer`]. /// /// # Errors - /// Will return Err if the associated [`IDIContainer`] already have a binding for + /// Will return Err if the associated [`DIContainer`] already have a binding for /// the interface. /// /// # Examples @@ -233,7 +218,6 @@ where /// # /// # use syrette::{DIContainer, factory}; /// # use syrette::ptr::TransientPtr; - /// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait IBuffer {} /// # @@ -271,18 +255,16 @@ 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, DIContainerType>, BindingBuilderError> + ) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError> where Return: 'static + ?Sized, FactoryFunc: Fn< - (Rc<DIContainerType>,), + (Rc<DIContainer>,), Output = crate::ptr::TransientPtr< dyn Fn<(), Output = crate::ptr::TransientPtr<Return>>, >, @@ -322,12 +304,13 @@ mod tests use super::*; use crate::dependency_history::MockDependencyHistory; - use crate::test_utils::{mocks, subjects}; + use crate::di_container::blocking::MockDIContainer; + use crate::test_utils::subjects; #[test] fn can_bind_to() -> Result<(), Box<dyn Error>> { - let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); + let mut mock_di_container = MockDIContainer::new(); mock_di_container .expect_has_binding::<dyn subjects::INumber>() @@ -341,11 +324,10 @@ mod tests .return_once(|_options, _provider| ()) .once(); - let binding_builder = - BindingBuilder::< - dyn subjects::INumber, - mocks::blocking_di_container::MockDIContainer, - >::new(Rc::new(mock_di_container), MockDependencyHistory::new); + let binding_builder = BindingBuilder::<dyn subjects::INumber>::new( + Rc::new(mock_di_container), + MockDependencyHistory::new, + ); binding_builder.to::<subjects::Number>()?; @@ -364,7 +346,7 @@ mod tests type IUserManagerFactory = dyn Fn(i32, String) -> TransientPtr<dyn subjects::IUserManager>; - let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); + let mut mock_di_container = MockDIContainer::new(); mock_di_container .expect_has_binding::<IUserManagerFactory>() @@ -378,11 +360,10 @@ mod tests .return_once(|_, _provider| ()) .once(); - let binding_builder = - BindingBuilder::< - IUserManagerFactory, - mocks::blocking_di_container::MockDIContainer, - >::new(Rc::new(mock_di_container), MockDependencyHistory::new); + let binding_builder = BindingBuilder::<IUserManagerFactory>::new( + Rc::new(mock_di_container), + MockDependencyHistory::new, + ); binding_builder.to_factory(&|_| { Box::new(move |_num, _text| { @@ -407,7 +388,7 @@ mod tests declare_default_factory!(dyn subjects::IUserManager); - let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); + let mut mock_di_container = MockDIContainer::new(); mock_di_container .expect_has_binding::<dyn subjects::IUserManager>() @@ -421,11 +402,10 @@ mod tests .return_once(|_, _provider| ()) .once(); - let binding_builder = - BindingBuilder::< - dyn subjects::IUserManager, - mocks::blocking_di_container::MockDIContainer, - >::new(Rc::new(mock_di_container), MockDependencyHistory::new); + let binding_builder = BindingBuilder::<dyn subjects::IUserManager>::new( + Rc::new(mock_di_container), + MockDependencyHistory::new, + ); binding_builder.to_default_factory(&|_| { Box::new(move || { diff --git a/src/di_container/blocking/binding/scope_configurator.rs b/src/di_container/blocking/binding/scope_configurator.rs index 0fcdfdf..be469ba 100644 --- a/src/di_container/blocking/binding/scope_configurator.rs +++ b/src/di_container/blocking/binding/scope_configurator.rs @@ -1,11 +1,8 @@ -//! Scope configurator for a binding for types inside of a [`IDIContainer`]. -//! -//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer +//! Scope configurator for a binding for types inside of a [`DIContainer`]. use std::marker::PhantomData; use std::rc::Rc; use crate::di_container::blocking::binding::when_configurator::BindingWhenConfigurator; -use crate::di_container::blocking::IDIContainer; use crate::di_container::BindingOptions; use crate::errors::di_container::BindingScopeConfiguratorError; use crate::interfaces::injectable::Injectable; @@ -14,32 +11,28 @@ use crate::ptr::SingletonPtr; use crate::util::use_double; use_double!(crate::dependency_history::DependencyHistory); +use_double!(crate::di_container::blocking::DIContainer); -/// Scope configurator for a binding for type `Interface` inside a [`IDIContainer`]. -/// -/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer -pub struct BindingScopeConfigurator<Interface, Implementation, DIContainerType> +/// Scope configurator for a binding for type `Interface` inside a [`DIContainer`]. +pub struct BindingScopeConfigurator<Interface, Implementation> where Interface: 'static + ?Sized, - Implementation: Injectable<DIContainerType>, - DIContainerType: IDIContainer, + Implementation: Injectable<DIContainer>, { - di_container: Rc<DIContainerType>, + di_container: Rc<DIContainer>, dependency_history_factory: fn() -> DependencyHistory, interface_phantom: PhantomData<Interface>, implementation_phantom: PhantomData<Implementation>, } -impl<Interface, Implementation, DIContainerType> - BindingScopeConfigurator<Interface, Implementation, DIContainerType> +impl<Interface, Implementation> BindingScopeConfigurator<Interface, Implementation> where Interface: 'static + ?Sized, - Implementation: Injectable<DIContainerType>, - DIContainerType: IDIContainer, + Implementation: Injectable<DIContainer>, { pub(crate) fn new( - di_container: Rc<DIContainerType>, + di_container: Rc<DIContainer>, dependency_history_factory: fn() -> DependencyHistory, ) -> Self { @@ -55,8 +48,7 @@ where /// /// This is the default. #[allow(clippy::must_use_candidate)] - pub fn in_transient_scope(self) - -> BindingWhenConfigurator<Interface, DIContainerType> + pub fn in_transient_scope(self) -> BindingWhenConfigurator<Interface> { self.set_in_transient_scope(); @@ -69,10 +61,7 @@ where /// Will return Err if resolving the implementation fails. pub fn in_singleton_scope( self, - ) -> Result< - BindingWhenConfigurator<Interface, DIContainerType>, - BindingScopeConfiguratorError, - > + ) -> Result<BindingWhenConfigurator<Interface>, BindingScopeConfiguratorError> { let singleton: SingletonPtr<Implementation> = SingletonPtr::from( Implementation::resolve( @@ -94,7 +83,7 @@ where { self.di_container.set_binding::<Interface>( BindingOptions::new(), - Box::new(TransientTypeProvider::<Implementation, DIContainerType>::new()), + Box::new(TransientTypeProvider::<Implementation, DIContainer>::new()), ); } } @@ -104,12 +93,13 @@ mod tests { use super::*; use crate::dependency_history::MockDependencyHistory; - use crate::test_utils::{mocks, subjects}; + use crate::di_container::blocking::MockDIContainer; + use crate::test_utils::subjects; #[test] fn in_transient_scope_works() { - let mut di_container_mock = mocks::blocking_di_container::MockDIContainer::new(); + let mut di_container_mock = MockDIContainer::new(); di_container_mock .expect_set_binding::<dyn subjects::IUserManager>() @@ -117,12 +107,13 @@ mod tests .return_once(|_name, _provider| ()) .once(); - let binding_scope_configurator = - BindingScopeConfigurator::< - dyn subjects::IUserManager, - subjects::UserManager, - mocks::blocking_di_container::MockDIContainer, - >::new(Rc::new(di_container_mock), MockDependencyHistory::new); + let binding_scope_configurator = BindingScopeConfigurator::< + dyn subjects::IUserManager, + subjects::UserManager, + >::new( + Rc::new(di_container_mock), + MockDependencyHistory::new, + ); binding_scope_configurator.in_transient_scope(); } @@ -130,7 +121,7 @@ mod tests #[test] fn in_singleton_scope_works() { - let mut di_container_mock = mocks::blocking_di_container::MockDIContainer::new(); + let mut di_container_mock = MockDIContainer::new(); di_container_mock .expect_set_binding::<dyn subjects::IUserManager>() @@ -138,12 +129,13 @@ mod tests .return_once(|_name, _provider| ()) .once(); - let binding_scope_configurator = - BindingScopeConfigurator::< - dyn subjects::IUserManager, - subjects::UserManager, - mocks::blocking_di_container::MockDIContainer, - >::new(Rc::new(di_container_mock), MockDependencyHistory::new); + let binding_scope_configurator = BindingScopeConfigurator::< + dyn subjects::IUserManager, + subjects::UserManager, + >::new( + Rc::new(di_container_mock), + MockDependencyHistory::new, + ); assert!(binding_scope_configurator.in_singleton_scope().is_ok()); } diff --git a/src/di_container/blocking/binding/when_configurator.rs b/src/di_container/blocking/binding/when_configurator.rs index 52b23ff..3d267b2 100644 --- a/src/di_container/blocking/binding/when_configurator.rs +++ b/src/di_container/blocking/binding/when_configurator.rs @@ -1,33 +1,29 @@ -//! When configurator for a binding for types inside of a [`IDIContainer`]. -//! -//! [`IDIContainer`]: crate::di_container::blocking::IDIContainer +//! When configurator for a binding for types inside of a [`DIContainer`]. use std::any::type_name; use std::marker::PhantomData; use std::rc::Rc; -use crate::di_container::blocking::IDIContainer; use crate::di_container::BindingOptions; use crate::errors::di_container::BindingWhenConfiguratorError; +use crate::util::use_double; -/// When configurator for a binding for type `Interface` inside a [`IDIContainer`]. -/// -/// [`IDIContainer`]: crate::di_container::blocking::IDIContainer -pub struct BindingWhenConfigurator<Interface, DIContainerType> +use_double!(crate::di_container::blocking::DIContainer); + +/// When configurator for a binding for type `Interface` inside a [`DIContainer`]. +pub struct BindingWhenConfigurator<Interface> where Interface: 'static + ?Sized, - DIContainerType: IDIContainer, { - di_container: Rc<DIContainerType>, + di_container: Rc<DIContainer>, interface_phantom: PhantomData<Interface>, } -impl<Interface, DIContainerType> BindingWhenConfigurator<Interface, DIContainerType> +impl<Interface> BindingWhenConfigurator<Interface> where Interface: 'static + ?Sized, - DIContainerType: IDIContainer, { - pub(crate) fn new(di_container: Rc<DIContainerType>) -> Self + pub(crate) fn new(di_container: Rc<DIContainer>) -> Self { Self { di_container, @@ -70,13 +66,14 @@ mod tests use mockall::predicate::eq; use super::*; + use crate::di_container::blocking::MockDIContainer; use crate::provider::blocking::MockIProvider; - use crate::test_utils::{mocks, subjects}; + use crate::test_utils::subjects; #[test] fn when_named_works() { - let mut di_container_mock = mocks::blocking_di_container::MockDIContainer::new(); + let mut di_container_mock = MockDIContainer::new(); di_container_mock .expect_remove_binding::<dyn subjects::INumber>() @@ -90,10 +87,10 @@ mod tests .return_once(|_name, _provider| ()) .once(); - let binding_when_configurator = BindingWhenConfigurator::< - dyn subjects::INumber, - mocks::blocking_di_container::MockDIContainer, - >::new(Rc::new(di_container_mock)); + let binding_when_configurator = + BindingWhenConfigurator::<dyn subjects::INumber>::new(Rc::new( + di_container_mock, + )); assert!(binding_when_configurator.when_named("cool").is_ok()); } diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index 27ea0fb..169abd2 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -5,7 +5,6 @@ //! use std::collections::HashMap; //! use std::error::Error; //! -//! use syrette::di_container::blocking::IDIContainer; //! use syrette::{injectable, DIContainer}; //! //! trait IDatabaseService @@ -69,15 +68,45 @@ use_double!(crate::dependency_history::DependencyHistory); pub mod binding; pub mod prelude; -/// Blocking dependency injection container interface. -/// -/// **This trait is sealed and cannot be implemented for types outside this crate.** -pub trait IDIContainer: Sized + 'static + details::DIContainerInternals +#[cfg(not(test))] +pub(crate) type BindingOptionsWithLt<'a> = BindingOptions<'a>; + +#[cfg(test)] +pub(crate) type BindingOptionsWithLt = BindingOptions<'static>; + +/// Blocking dependency injection container. +pub struct DIContainer +{ + binding_storage: RefCell<DIContainerBindingStorage<dyn IProvider<Self>>>, +} + +impl DIContainer +{ + /// Returns a new `DIContainer`. + #[must_use] + pub fn new() -> Rc<Self> + { + Rc::new(Self { + binding_storage: RefCell::new(DIContainerBindingStorage::new()), + }) + } +} + +#[cfg_attr(test, mockall::automock)] +impl DIContainer { /// Returns a new [`BindingBuilder`] for the given interface. - fn bind<Interface>(self: &mut Rc<Self>) -> BindingBuilder<Interface, Self> + #[allow(clippy::missing_panics_doc)] + pub fn bind<Interface>(self: &mut Rc<Self>) -> BindingBuilder<Interface> where - Interface: 'static + ?Sized; + Interface: 'static + ?Sized, + { + #[cfg(test)] + panic!("Nope"); + + #[cfg(not(test))] + BindingBuilder::new(self.clone(), DependencyHistory::new) + } /// Returns the type bound with `Interface`. /// @@ -86,9 +115,12 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals /// - No binding for `Interface` exists /// - Resolving the binding for `Interface` fails /// - Casting the binding for `Interface` fails - fn get<Interface>(self: &Rc<Self>) -> Result<SomePtr<Interface>, DIContainerError> + pub fn get<Interface>(self: &Rc<Self>) -> Result<SomePtr<Interface>, DIContainerError> where - Interface: 'static + ?Sized; + Interface: 'static + ?Sized, + { + self.get_bound::<Interface>(DependencyHistory::new(), BindingOptions::new()) + } /// Returns the type bound with `Interface` and the specified name. /// @@ -97,12 +129,18 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals /// - No binding for `Interface` with name `name` exists /// - Resolving the binding for `Interface` fails /// - Casting the binding for `Interface` fails - fn get_named<Interface>( + pub fn get_named<Interface>( self: &Rc<Self>, name: &'static str, ) -> Result<SomePtr<Interface>, DIContainerError> where - Interface: 'static + ?Sized; + Interface: 'static + ?Sized, + { + self.get_bound::<Interface>( + DependencyHistory::new(), + BindingOptions::new().name(name), + ) + } /// Returns the type bound with `Interface` where the binding has the specified /// options. @@ -118,7 +156,6 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals /// # Examples /// ```no_run /// # use syrette::di_container::blocking::DIContainer; - /// # use syrette::di_container::blocking::IDIContainer; /// # use syrette::dependency_history::DependencyHistory; /// # use syrette::di_container::BindingOptions; /// # @@ -140,132 +177,17 @@ pub trait IDIContainer: Sized + 'static + details::DIContainerInternals /// # Ok(()) /// # } /// ``` - fn get_bound<Interface>( + pub fn get_bound<Interface>( self: &Rc<Self>, dependency_history: DependencyHistory, binding_options: BindingOptionsWithLt, ) -> Result<SomePtr<Interface>, DIContainerError> where - Interface: 'static + ?Sized; -} - -#[cfg(not(test))] -pub(crate) type BindingOptionsWithLt<'a> = BindingOptions<'a>; - -#[cfg(test)] -pub(crate) type BindingOptionsWithLt = BindingOptions<'static>; - -/// Blocking dependency injection container. -pub struct DIContainer -{ - binding_storage: RefCell<DIContainerBindingStorage<dyn IProvider<Self>>>, -} - -impl DIContainer -{ - /// Returns a new `DIContainer`. - #[must_use] - pub fn new() -> Rc<Self> - { - Rc::new(Self { - binding_storage: RefCell::new(DIContainerBindingStorage::new()), - }) - } -} - -impl IDIContainer for DIContainer -{ - fn bind<Interface>(self: &mut Rc<Self>) -> BindingBuilder<Interface, Self> - where - Interface: 'static + ?Sized, - { - BindingBuilder::new(self.clone(), DependencyHistory::new) - } - - fn get<Interface>(self: &Rc<Self>) -> Result<SomePtr<Interface>, DIContainerError> - where - Interface: 'static + ?Sized, - { - self.get_bound::<Interface>(DependencyHistory::new(), BindingOptions::new()) - } - - fn get_named<Interface>( - self: &Rc<Self>, - name: &'static str, - ) -> Result<SomePtr<Interface>, DIContainerError> - where - Interface: 'static + ?Sized, - { - self.get_bound::<Interface>( - DependencyHistory::new(), - BindingOptions::new().name(name), - ) - } - - fn get_bound<Interface>( - self: &Rc<Self>, - dependency_history: DependencyHistory, - binding_options: BindingOptions, - ) -> Result<SomePtr<Interface>, DIContainerError> - where Interface: 'static + ?Sized, { let binding_providable = self .get_binding_providable::<Interface>(binding_options, dependency_history)?; - #[cfg(feature = "factory")] - return self.handle_binding_providable(binding_providable); - - #[cfg(not(feature = "factory"))] - Self::handle_binding_providable(binding_providable) - } -} - -impl details::DIContainerInternals for DIContainer -{ - fn has_binding<Interface>(self: &Rc<Self>, binding_options: BindingOptions) -> bool - where - Interface: ?Sized + 'static, - { - self.binding_storage - .borrow() - .has::<Interface>(binding_options) - } - - fn set_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptions<'static>, - provider: Box<dyn IProvider<Self>>, - ) where - Interface: 'static + ?Sized, - { - self.binding_storage - .borrow_mut() - .set::<Interface>(binding_options, provider); - } - - fn remove_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptions<'static>, - ) -> Option<Box<dyn IProvider<Self>>> - where - Interface: 'static + ?Sized, - { - self.binding_storage - .borrow_mut() - .remove::<Interface>(binding_options) - } -} - -impl DIContainer -{ - fn handle_binding_providable<Interface>( - #[cfg(feature = "factory")] self: &Rc<Self>, - binding_providable: Providable<Self>, - ) -> Result<SomePtr<Interface>, DIContainerError> - where - Interface: 'static + ?Sized, - { match binding_providable { Providable::Transient(transient_binding) => Ok(SomePtr::Transient( transient_binding.cast::<Interface>().map_err(|_| { @@ -318,7 +240,7 @@ impl DIContainer fn get_binding_providable<Interface>( self: &Rc<Self>, - binding_options: BindingOptions, + binding_options: BindingOptionsWithLt, dependency_history: DependencyHistory, ) -> Result<Providable<Self>, DIContainerError> where @@ -344,38 +266,41 @@ impl DIContainer interface: type_name::<Interface>(), }) } -} -pub(crate) mod details -{ - use std::rc::Rc; + fn has_binding<Interface>( + self: &Rc<Self>, + binding_options: BindingOptionsWithLt, + ) -> bool + where + Interface: ?Sized + 'static, + { + self.binding_storage + .borrow() + .has::<Interface>(binding_options) + } - use crate::di_container::blocking::BindingOptionsWithLt; - use crate::di_container::BindingOptions; - use crate::provider::blocking::IProvider; + fn set_binding<Interface>( + self: &Rc<Self>, + binding_options: BindingOptions<'static>, + provider: Box<dyn IProvider<Self>>, + ) where + Interface: 'static + ?Sized, + { + self.binding_storage + .borrow_mut() + .set::<Interface>(binding_options, provider); + } - pub trait DIContainerInternals + fn remove_binding<Interface>( + self: &Rc<Self>, + binding_options: BindingOptions<'static>, + ) -> Option<Box<dyn IProvider<Self>>> + where + Interface: 'static + ?Sized, { - fn has_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptionsWithLt, - ) -> bool - where - Interface: ?Sized + 'static; - - fn set_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptions<'static>, - provider: Box<dyn IProvider<Self>>, - ) where - Interface: 'static + ?Sized; - - fn remove_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptions<'static>, - ) -> Option<Box<dyn IProvider<Self>>> - where - Interface: 'static + ?Sized; + self.binding_storage + .borrow_mut() + .remove::<Interface>(binding_options) } } @@ -385,15 +310,16 @@ mod tests use std::error::Error; use super::*; + use crate::provider::blocking::MockIProvider; use crate::ptr::{SingletonPtr, TransientPtr}; - use crate::test_utils::{mocks, subjects}; + use crate::test_utils::subjects; #[test] fn can_get() -> Result<(), Box<dyn Error>> { let di_container = DIContainer::new(); - let mut mock_provider = mocks::blocking_provider::MockProvider::new(); + let mut mock_provider = MockIProvider::new(); mock_provider.expect_provide().returning(|_, _| { Ok(Providable::Transient(TransientPtr::new( @@ -421,7 +347,7 @@ mod tests { let di_container = DIContainer::new(); - let mut mock_provider = mocks::blocking_provider::MockProvider::new(); + let mut mock_provider = MockIProvider::new(); mock_provider.expect_provide().returning(|_, _| { Ok(Providable::Transient(TransientPtr::new( @@ -449,7 +375,7 @@ mod tests { let di_container = DIContainer::new(); - let mut mock_provider = mocks::blocking_provider::MockProvider::new(); + let mut mock_provider = MockIProvider::new(); let mut singleton = SingletonPtr::new(subjects::Number::new()); @@ -481,7 +407,7 @@ mod tests { let di_container = DIContainer::new(); - let mut mock_provider = mocks::blocking_provider::MockProvider::new(); + let mut mock_provider = MockIProvider::new(); let mut singleton = SingletonPtr::new(subjects::Number::new()); @@ -574,7 +500,7 @@ mod tests }) }; - let mut mock_provider = mocks::blocking_provider::MockProvider::new(); + let mut mock_provider = MockIProvider::new(); mock_provider.expect_provide().returning_st(|_, _| { Ok(Providable::Factory(FactoryPtr::new(CastableFactory::new( @@ -652,7 +578,7 @@ mod tests }) }; - let mut mock_provider = mocks::blocking_provider::MockProvider::new(); + let mut mock_provider = MockIProvider::new(); mock_provider.expect_provide().returning_st(|_, _| { Ok(Providable::Factory(FactoryPtr::new(CastableFactory::new( @@ -674,4 +600,68 @@ mod tests Ok(()) } + + #[test] + fn has_binding_works() + { + let di_container = DIContainer::new(); + + // No binding is present yet + assert!(!di_container.has_binding::<subjects::Ninja>(BindingOptions::new())); + + di_container + .binding_storage + .borrow_mut() + .set::<subjects::Ninja>( + BindingOptions::new(), + Box::new(MockIProvider::new()), + ); + + assert!(di_container.has_binding::<subjects::Ninja>(BindingOptions::new())); + } + + #[test] + fn set_binding_works() + { + let di_container = DIContainer::new(); + + di_container.set_binding::<subjects::Ninja>( + BindingOptions::new(), + Box::new(MockIProvider::new()), + ); + + assert!(di_container + .binding_storage + .borrow_mut() + .has::<subjects::Ninja>(BindingOptions::new())); + } + + #[test] + fn remove_binding_works() + { + let di_container = DIContainer::new(); + + di_container + .binding_storage + .borrow_mut() + .set::<subjects::Ninja>( + BindingOptions::new(), + Box::new(MockIProvider::new()), + ); + + assert!( + // Formatting is weird without this comment + di_container + .remove_binding::<subjects::Ninja>(BindingOptions::new()) + .is_some() + ); + + assert!( + // Formatting is weird without this comment + !di_container + .binding_storage + .borrow_mut() + .has::<subjects::Ninja>(BindingOptions::new()) + ); + } } diff --git a/src/di_container/blocking/prelude.rs b/src/di_container/blocking/prelude.rs index 82db5e3..216be4b 100644 --- a/src/di_container/blocking/prelude.rs +++ b/src/di_container/blocking/prelude.rs @@ -1,2 +1,2 @@ //! Commonly used types. -pub use crate::di_container::blocking::{DIContainer, IDIContainer}; +pub use crate::di_container::blocking::DIContainer; diff --git a/src/interfaces/injectable.rs b/src/interfaces/injectable.rs index 2622320..458b167 100644 --- a/src/interfaces/injectable.rs +++ b/src/interfaces/injectable.rs @@ -2,7 +2,6 @@ use std::fmt::Debug; use std::rc::Rc; -use crate::di_container::blocking::IDIContainer; use crate::errors::injectable::InjectableError; use crate::private::cast::CastFrom; use crate::ptr::TransientPtr; @@ -11,25 +10,21 @@ use crate::util::use_double; use_double!(crate::dependency_history::DependencyHistory); /// Interface for structs that can be injected into or be injected to. -pub trait Injectable<DIContainerType>: CastFrom -where - DIContainerType: IDIContainer, +pub trait Injectable<DIContainerT>: CastFrom { /// Resolves the dependencies of the injectable. /// /// # Errors /// Will return `Err` if resolving the dependencies fails. fn resolve( - di_container: &Rc<DIContainerType>, + di_container: &Rc<DIContainerT>, dependency_history: DependencyHistory, ) -> Result<TransientPtr<Self>, InjectableError> where Self: Sized; } -impl<DIContainerType> Debug for dyn Injectable<DIContainerType> -where - DIContainerType: IDIContainer, +impl<DIContainerT> Debug for dyn Injectable<DIContainerT> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -131,7 +131,6 @@ mod test_utils; /// # Examples /// ``` /// # use syrette::{di_container_bind, DIContainer, injectable}; -/// # use syrette::di_container::blocking::IDIContainer; /// # /// # trait INinja {} /// # diff --git a/src/provider/blocking.rs b/src/provider/blocking.rs index bc9134d..c719f59 100644 --- a/src/provider/blocking.rs +++ b/src/provider/blocking.rs @@ -1,7 +1,6 @@ use std::marker::PhantomData; use std::rc::Rc; -use crate::di_container::blocking::IDIContainer; use crate::errors::injectable::InjectableError; use crate::interfaces::injectable::Injectable; use crate::ptr::{SingletonPtr, TransientPtr}; @@ -11,8 +10,6 @@ use_double!(crate::dependency_history::DependencyHistory); #[derive(strum_macros::Display, Debug)] pub enum Providable<DIContainerType> -where - DIContainerType: IDIContainer, { Transient(TransientPtr<dyn Injectable<DIContainerType>>), Singleton(SingletonPtr<dyn Injectable<DIContainerType>>), @@ -22,10 +19,8 @@ where DefaultFactory(crate::ptr::FactoryPtr<dyn crate::private::any_factory::AnyFactory>), } -#[cfg_attr(test, mockall::automock, allow(dead_code))] +#[cfg_attr(test, mockall::automock)] pub trait IProvider<DIContainerType> -where - DIContainerType: IDIContainer, { fn provide( &self, @@ -37,7 +32,6 @@ where pub struct TransientTypeProvider<InjectableType, DIContainerType> where InjectableType: Injectable<DIContainerType>, - DIContainerType: IDIContainer, { injectable_phantom: PhantomData<InjectableType>, di_container_phantom: PhantomData<DIContainerType>, @@ -47,7 +41,6 @@ impl<InjectableType, DIContainerType> TransientTypeProvider<InjectableType, DIContainerType> where InjectableType: Injectable<DIContainerType>, - DIContainerType: IDIContainer, { pub fn new() -> Self { @@ -62,7 +55,6 @@ impl<InjectableType, DIContainerType> IProvider<DIContainerType> for TransientTypeProvider<InjectableType, DIContainerType> where InjectableType: Injectable<DIContainerType>, - DIContainerType: IDIContainer, { fn provide( &self, @@ -80,7 +72,6 @@ where pub struct SingletonProvider<InjectableType, DIContainerType> where InjectableType: Injectable<DIContainerType>, - DIContainerType: IDIContainer, { singleton: SingletonPtr<InjectableType>, @@ -90,7 +81,6 @@ where impl<InjectableType, DIContainerType> SingletonProvider<InjectableType, DIContainerType> where InjectableType: Injectable<DIContainerType>, - DIContainerType: IDIContainer, { pub fn new(singleton: SingletonPtr<InjectableType>) -> Self { @@ -105,7 +95,6 @@ impl<InjectableType, DIContainerType> IProvider<DIContainerType> for SingletonProvider<InjectableType, DIContainerType> where InjectableType: Injectable<DIContainerType>, - DIContainerType: IDIContainer, { fn provide( &self, @@ -141,8 +130,6 @@ impl FactoryProvider #[cfg(feature = "factory")] impl<DIContainerType> IProvider<DIContainerType> for FactoryProvider -where - DIContainerType: IDIContainer, { fn provide( &self, @@ -165,17 +152,16 @@ mod tests use super::*; use crate::dependency_history::MockDependencyHistory; - use crate::test_utils::{mocks, subjects}; + use crate::di_container::blocking::MockDIContainer; + use crate::test_utils::subjects; #[test] fn transient_type_provider_works() -> Result<(), Box<dyn Error>> { - let transient_type_provider = TransientTypeProvider::< - subjects::UserManager, - mocks::blocking_di_container::MockDIContainer, - >::new(); + let transient_type_provider = + TransientTypeProvider::<subjects::UserManager, MockDIContainer>::new(); - let di_container = mocks::blocking_di_container::MockDIContainer::new(); + let di_container = MockDIContainer::new(); let dependency_history_mock = MockDependencyHistory::new(); @@ -195,12 +181,11 @@ mod tests fn singleton_provider_works() -> Result<(), Box<dyn Error>> { let singleton_provider = - SingletonProvider::< - subjects::UserManager, - mocks::blocking_di_container::MockDIContainer, - >::new(SingletonPtr::new(subjects::UserManager {})); + SingletonProvider::<subjects::UserManager, MockDIContainer>::new( + SingletonPtr::new(subjects::UserManager {}), + ); - let di_container = mocks::blocking_di_container::MockDIContainer::new(); + let di_container = MockDIContainer::new(); assert!( matches!( @@ -230,7 +215,7 @@ mod tests let default_factory_provider = FactoryProvider::new(FactoryPtr::new(FooFactory), true); - let di_container = Rc::new(mocks::blocking_di_container::MockDIContainer::new()); + let di_container = Rc::new(MockDIContainer::new()); assert!( matches!( diff --git a/src/test_utils.rs b/src/test_utils.rs index a304a71..95b7ce1 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -7,7 +7,6 @@ pub mod subjects use syrette_macros::declare_interface; - use crate::di_container::blocking::IDIContainer; use crate::interfaces::injectable::Injectable; use crate::private::cast::CastFromArc; use crate::ptr::TransientPtr; @@ -49,12 +48,10 @@ pub mod subjects declare_interface!(UserManager -> IUserManager); - impl<DIContainerType> Injectable<DIContainerType> for UserManager - where - DIContainerType: IDIContainer, + impl<DIContainerT> Injectable<DIContainerT> for UserManager { fn resolve( - _di_container: &Rc<DIContainerType>, + _di_container: &Rc<DIContainerT>, _dependency_history: DependencyHistory, ) -> Result<TransientPtr<Self>, crate::errors::injectable::InjectableError> where @@ -115,12 +112,10 @@ pub mod subjects declare_interface!(Number -> INumber); - impl<DIContainerType> Injectable<DIContainerType> for Number - where - DIContainerType: IDIContainer, + impl<DIContainerT> Injectable<DIContainerT> for Number { fn resolve( - _di_container: &Rc<DIContainerType>, + _di_container: &Rc<DIContainerT>, _dependency_history: DependencyHistory, ) -> Result<TransientPtr<Self>, crate::errors::injectable::InjectableError> where @@ -279,87 +274,13 @@ pub mod mocks #![allow(clippy::ref_option_ref)] // Caused by Mockall #![allow(dead_code)] // Not all mock functions may be used - use mockall::mock; - - pub mod blocking_di_container - { - use std::rc::Rc; - - use super::*; - use crate::di_container::blocking::binding::builder::BindingBuilder; - use crate::di_container::blocking::details::DIContainerInternals; - use crate::di_container::blocking::{BindingOptionsWithLt, IDIContainer}; - use crate::di_container::BindingOptions; - use crate::errors::di_container::DIContainerError; - use crate::provider::blocking::IProvider; - use crate::ptr::SomePtr; - use crate::util::use_double; - - use_double!(crate::dependency_history::DependencyHistory); - - mock! { - pub DIContainer {} - - impl IDIContainer for DIContainer - { - fn bind<Interface>(self: &mut Rc<Self>) -> BindingBuilder<Interface, Self> - where - Interface: 'static + ?Sized; - - fn get<Interface>(self: &Rc<Self>) -> Result<SomePtr<Interface>, DIContainerError> - where - Interface: 'static + ?Sized; - - fn get_named<Interface>( - self: &Rc<Self>, - name: &'static str, - ) -> Result<SomePtr<Interface>, DIContainerError> - where - Interface: 'static + ?Sized; - - #[doc(hidden)] - fn get_bound<'opts, Interface>( - self: &Rc<Self>, - dependency_history: DependencyHistory, - binding_options: BindingOptionsWithLt, - ) -> Result<SomePtr<Interface>, DIContainerError> - where - Interface: 'static + ?Sized; - } - - impl DIContainerInternals for DIContainer - { - fn has_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptionsWithLt - ) -> bool - where - Interface: ?Sized + 'static; - - #[doc(hidden)] - fn set_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptions<'static>, - provider: Box<dyn IProvider<Self>>, - ) where - Interface: 'static + ?Sized; - - fn remove_binding<Interface>( - self: &Rc<Self>, - binding_options: BindingOptions<'static>, - ) -> Option<Box<dyn IProvider<Self>>> - where - Interface: 'static + ?Sized; - } - } - } - #[cfg(feature = "async")] pub mod async_di_container { use std::sync::Arc; - use super::*; + use mockall::mock; + use crate::di_container::asynchronous::binding::builder::AsyncBindingBuilder; use crate::di_container::asynchronous::details::DIContainerInternals; use crate::di_container::asynchronous::IAsyncDIContainer; @@ -438,8 +359,8 @@ pub mod mocks use std::sync::Arc; use async_trait::async_trait; + use mockall::mock; - use super::*; use crate::di_container::asynchronous::IAsyncDIContainer; use crate::errors::injectable::InjectableError; use crate::provider::r#async::{AsyncProvidable, IAsyncProvider}; @@ -468,37 +389,6 @@ pub mod mocks } } } - - pub mod blocking_provider - { - use std::rc::Rc; - - use super::*; - use crate::di_container::blocking::IDIContainer; - use crate::errors::injectable::InjectableError; - use crate::provider::blocking::{IProvider, Providable}; - use crate::util::use_double; - - use_double!(crate::dependency_history::DependencyHistory); - - mock! { - pub Provider<DIContainerType> - where - DIContainerType: IDIContainer - {} - - impl<DIContainerType> IProvider<DIContainerType> for Provider<DIContainerType> - where - DIContainerType: IDIContainer, - { - fn provide( - &self, - di_container: &Rc<DIContainerType>, - dependency_history: DependencyHistory, - ) -> Result<Providable<DIContainerType>, InjectableError>; - } - } - } } #[cfg(all(feature = "async", feature = "factory"))] |