diff options
author | HampusM <hampus@hampusmat.com> | 2023-09-14 19:41:56 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-09-14 21:17:37 +0200 |
commit | 9bed6b4d2772fd020ea9eb6eaaba4ca014d96f94 (patch) | |
tree | dff0d7768f4a56c9d75e4a6c89974891373e997b /src/di_container/blocking/mod.rs | |
parent | 9a7cf8cfd376da09c982606aa79f253319dfe382 (diff) |
refactor!: remove blocking DI container interface
BREAKING CHANGE: IDIContainer have been removed and multiple structs no longer take a DI container generic parameter
Diffstat (limited to 'src/di_container/blocking/mod.rs')
-rw-r--r-- | src/di_container/blocking/mod.rs | 318 |
1 files changed, 154 insertions, 164 deletions
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()) + ); + } } |