aboutsummaryrefslogtreecommitdiff
path: root/src/async_di_container.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-09-24 17:31:16 +0200
committerHampusM <hampus@hampusmat.com>2022-09-24 17:33:10 +0200
commitfdd7f824fd1244226ca86f525f8439744676688f (patch)
tree073019e506e36578caeab894835ccf51dc5d7584 /src/async_di_container.rs
parentfebfb927b27ab03041500b16c65bdbc0624a5a72 (diff)
feat: add bind async default factories to async DI container
Diffstat (limited to 'src/async_di_container.rs')
-rw-r--r--src/async_di_container.rs139
1 files changed, 111 insertions, 28 deletions
diff --git a/src/async_di_container.rs b/src/async_di_container.rs
index d90cc0b..894b707 100644
--- a/src/async_di_container.rs
+++ b/src/async_di_container.rs
@@ -69,6 +69,7 @@ use crate::errors::async_di_container::{
AsyncBindingWhenConfiguratorError,
AsyncDIContainerError,
};
+use crate::future::BoxFuture;
use crate::interfaces::async_injectable::AsyncInjectable;
use crate::libs::intertrait::cast::error::CastError;
use crate::libs::intertrait::cast::{CastArc, CastBox};
@@ -274,6 +275,8 @@ where
> + Send
+ Sync,
{
+ use crate::provider::r#async::AsyncFactoryVariant;
+
let mut bindings_lock = self.di_container.bindings.lock().await;
if bindings_lock.has::<Interface>(None) {
@@ -289,7 +292,7 @@ where
None,
Box::new(crate::provider::r#async::AsyncFactoryProvider::new(
crate::ptr::ThreadsafeFactoryPtr::new(factory_impl),
- false,
+ AsyncFactoryVariant::Normal,
)),
);
@@ -313,7 +316,8 @@ where
where
Args: 'static,
Return: 'static + ?Sized,
- Interface: Fn<Args, Output = crate::future::BoxFuture<'static, Return>>,
+ Interface:
+ Fn<Args, Output = crate::future::BoxFuture<'static, Return>> + Send + Sync,
FactoryFunc: Fn<
(Arc<AsyncDIContainer>,),
Output = Box<
@@ -324,6 +328,8 @@ where
> + Send
+ Sync,
{
+ use crate::provider::r#async::AsyncFactoryVariant;
+
let mut bindings_lock = self.di_container.bindings.lock().await;
if bindings_lock.has::<Interface>(None) {
@@ -339,7 +345,7 @@ where
None,
Box::new(crate::provider::r#async::AsyncFactoryProvider::new(
crate::ptr::ThreadsafeFactoryPtr::new(factory_impl),
- false,
+ AsyncFactoryVariant::Normal,
)),
);
@@ -369,6 +375,58 @@ where
> + Send
+ Sync,
{
+ use crate::provider::r#async::AsyncFactoryVariant;
+
+ let mut bindings_lock = self.di_container.bindings.lock().await;
+
+ if bindings_lock.has::<Interface>(None) {
+ return Err(AsyncBindingBuilderError::BindingAlreadyExists(type_name::<
+ Interface,
+ >(
+ )));
+ }
+
+ 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,
+ )),
+ );
+
+ Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))
+ }
+
+ /// Creates a binding of factory type `Interface` to a async factory inside of the
+ /// associated [`AsyncDIContainer`].
+ ///
+ /// *This function is only available if Syrette is built with the "factory" and
+ /// "async" features.*
+ ///
+ /// # Errors
+ /// Will return Err if the associated [`AsyncDIContainer`] already have a binding for
+ /// the interface.
+ #[cfg(all(feature = "factory", feature = "async"))]
+ pub async fn to_async_default_factory<Return, FactoryFunc>(
+ &self,
+ factory_func: &'static FactoryFunc,
+ ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError>
+ where
+ Return: 'static + ?Sized,
+ FactoryFunc: Fn<
+ (Arc<AsyncDIContainer>,),
+ Output = Box<
+ (dyn Fn<(), Output = crate::future::BoxFuture<'static, Return>>
+ + Send
+ + Sync),
+ >,
+ > + Send
+ + Sync,
+ {
+ use crate::provider::r#async::AsyncFactoryVariant;
+
let mut bindings_lock = self.di_container.bindings.lock().await;
if bindings_lock.has::<Interface>(None) {
@@ -384,7 +442,7 @@ where
None,
Box::new(crate::provider::r#async::AsyncFactoryProvider::new(
crate::ptr::ThreadsafeFactoryPtr::new(factory_impl),
- true,
+ AsyncFactoryVariant::AsyncDefault,
)),
);
@@ -464,10 +522,10 @@ impl AsyncDIContainer
.get_binding_providable::<Interface>(name, dependency_history)
.await?;
- self.handle_binding_providable(binding_providable)
+ self.handle_binding_providable(binding_providable).await
}
- fn handle_binding_providable<Interface>(
+ async fn handle_binding_providable<Interface>(
self: &Arc<Self>,
binding_providable: AsyncProvidable,
) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>
@@ -507,11 +565,10 @@ impl AsyncDIContainer
}
#[cfg(feature = "factory")]
AsyncProvidable::Factory(factory_binding) => {
+ use crate::interfaces::factory::IThreadsafeFactory;
+
let factory = factory_binding
- .cast::<dyn crate::interfaces::factory::IFactory<
- (Arc<AsyncDIContainer>,),
- Interface,
- >>()
+ .cast::<dyn IThreadsafeFactory<(Arc<AsyncDIContainer>,), Interface>>()
.map_err(|err| match err {
CastError::NotArcCastable(_) => {
AsyncDIContainerError::InterfaceNotAsync(
@@ -531,33 +588,59 @@ impl AsyncDIContainer
))
}
#[cfg(feature = "factory")]
- AsyncProvidable::DefaultFactory(default_factory_binding) => {
- use crate::interfaces::factory::IFactory;
+ AsyncProvidable::DefaultFactory(binding) => {
+ use crate::interfaces::factory::IThreadsafeFactory;
- let default_factory = default_factory_binding
- .cast::<dyn IFactory<
+ let default_factory = Self::cast_factory_binding::<
+ dyn IThreadsafeFactory<
(Arc<AsyncDIContainer>,),
dyn Fn<(), Output = TransientPtr<Interface>> + Send + Sync,
- >>()
- .map_err(|err| match err {
- CastError::NotArcCastable(_) => {
- AsyncDIContainerError::InterfaceNotAsync(
- type_name::<Interface>(),
- )
- }
- CastError::CastFailed { from: _, to: _ } => {
- AsyncDIContainerError::CastFailed {
- interface: type_name::<Interface>(),
- binding_kind: "default factory",
- }
- }
- })?;
+ >,
+ >(binding, "default factory")?;
Ok(SomeThreadsafePtr::Transient(default_factory(self.clone())()))
}
+ #[cfg(feature = "factory")]
+ AsyncProvidable::AsyncDefaultFactory(binding) => {
+ use crate::interfaces::factory::IThreadsafeFactory;
+
+ let async_default_factory = Self::cast_factory_binding::<
+ dyn IThreadsafeFactory<
+ (Arc<AsyncDIContainer>,),
+ dyn Fn<(), Output = BoxFuture<'static, TransientPtr<Interface>>>
+ + Send
+ + Sync,
+ >,
+ >(
+ binding, "async default factory"
+ )?;
+
+ Ok(SomeThreadsafePtr::Transient(
+ async_default_factory(self.clone())().await,
+ ))
+ }
}
}
+ #[cfg(feature = "factory")]
+ fn cast_factory_binding<Type: 'static + ?Sized>(
+ factory_binding: Arc<dyn crate::interfaces::any_factory::AnyThreadsafeFactory>,
+ binding_kind: &'static str,
+ ) -> Result<Arc<Type>, AsyncDIContainerError>
+ {
+ factory_binding.cast::<Type>().map_err(|err| match err {
+ CastError::NotArcCastable(_) => {
+ AsyncDIContainerError::InterfaceNotAsync(type_name::<Type>())
+ }
+ CastError::CastFailed { from: _, to: _ } => {
+ AsyncDIContainerError::CastFailed {
+ interface: type_name::<Type>(),
+ binding_kind,
+ }
+ }
+ })
+ }
+
async fn get_binding_providable<Interface>(
self: &Arc<Self>,
name: Option<&'static str>,