aboutsummaryrefslogtreecommitdiff
path: root/src/di_container/blocking/mod.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-09-14 19:41:56 +0200
committerHampusM <hampus@hampusmat.com>2023-09-14 21:17:37 +0200
commit9bed6b4d2772fd020ea9eb6eaaba4ca014d96f94 (patch)
treedff0d7768f4a56c9d75e4a6c89974891373e997b /src/di_container/blocking/mod.rs
parent9a7cf8cfd376da09c982606aa79f253319dfe382 (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.rs318
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())
+ );
+ }
}