aboutsummaryrefslogtreecommitdiff
path: root/src/di_container/asynchronous/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/di_container/asynchronous/mod.rs')
-rw-r--r--src/di_container/asynchronous/mod.rs217
1 files changed, 166 insertions, 51 deletions
diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs
index b6653a5..14e6abe 100644
--- a/src/di_container/asynchronous/mod.rs
+++ b/src/di_container/asynchronous/mod.rs
@@ -5,7 +5,8 @@
//! use std::collections::HashMap;
//! use std::error::Error;
//!
-//! use syrette::{injectable, AsyncDIContainer};
+//! use syrette::di_container::asynchronous::prelude::*;
+//! use syrette::injectable;
//!
//! trait IDatabaseService: Send + Sync
//! {
@@ -53,6 +54,7 @@
use std::any::type_name;
use std::sync::Arc;
+use async_trait::async_trait;
use tokio::sync::Mutex;
use crate::di_container::asynchronous::binding::builder::AsyncBindingBuilder;
@@ -65,11 +67,64 @@ use crate::provider::r#async::{AsyncProvidable, IAsyncProvider};
use crate::ptr::{SomeThreadsafePtr, TransientPtr};
pub mod binding;
+pub mod prelude;
+
+/// Dependency injection container interface.
+#[async_trait]
+pub trait IAsyncDIContainer:
+ Sized + 'static + Send + Sync + details::DIContainerInternals
+{
+ /// Returns a new [`AsyncBindingBuilder`] for the given interface.
+ #[must_use]
+ fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface, Self>
+ where
+ Interface: 'static + ?Sized + Send + Sync;
+
+ /// Returns the type bound with `Interface`.
+ ///
+ /// # Errors
+ /// Will return `Err` if:
+ /// - No binding for `Interface` exists
+ /// - Resolving the binding for `Interface` fails
+ /// - Casting the binding for `Interface` fails
+ fn get<'a, 'b, Interface>(
+ self: &'a Arc<Self>,
+ ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>>
+ where
+ Interface: 'static + 'b + ?Sized + Send + Sync,
+ 'a: 'b,
+ Self: 'b;
+
+ /// Returns the type bound with `Interface` and the specified name.
+ ///
+ /// # Errors
+ /// Will return `Err` if:
+ /// - No binding for `Interface` with name `name` exists
+ /// - Resolving the binding for `Interface` fails
+ /// - Casting the binding for `Interface` fails
+ fn get_named<'a, 'b, Interface>(
+ self: &'a Arc<Self>,
+ name: &'static str,
+ ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>>
+ where
+ Interface: 'static + 'b + ?Sized + Send + Sync,
+ 'a: 'b,
+ Self: 'b;
+
+ #[doc(hidden)]
+ async fn get_bound<Interface>(
+ self: &Arc<Self>,
+ dependency_history: Vec<&'static str>,
+ name: Option<&'static str>,
+ ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>
+ where
+ Interface: 'static + ?Sized + Send + Sync;
+}
/// Dependency injection container.
pub struct AsyncDIContainer
{
- bindings: Mutex<DIContainerBindingMap<dyn IAsyncProvider>>,
+ bindings: Mutex<DIContainerBindingMap<dyn IAsyncProvider<Self>>>,
}
impl AsyncDIContainer
@@ -82,51 +137,43 @@ impl AsyncDIContainer
bindings: Mutex::new(DIContainerBindingMap::new()),
})
}
+}
- /// Returns a new [`AsyncBindingBuilder`] for the given interface.
+#[async_trait]
+impl IAsyncDIContainer for AsyncDIContainer
+{
#[must_use]
- pub fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface>
+ fn bind<Interface>(self: &mut Arc<Self>) -> AsyncBindingBuilder<Interface, Self>
where
Interface: 'static + ?Sized + Send + Sync,
{
- AsyncBindingBuilder::<Interface>::new(self.clone())
+ AsyncBindingBuilder::new(self.clone())
}
- /// Returns the type bound with `Interface`.
- ///
- /// # Errors
- /// Will return `Err` if:
- /// - No binding for `Interface` exists
- /// - Resolving the binding for `Interface` fails
- /// - Casting the binding for `Interface` fails
- pub async fn get<Interface>(
- self: &Arc<Self>,
- ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>
+ fn get<'a, 'b, Interface>(
+ self: &'a Arc<Self>,
+ ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>>
where
- Interface: 'static + ?Sized + Send + Sync,
+ Interface: 'static + 'b + ?Sized + Send + Sync,
+ 'a: 'b,
+ Self: 'b,
{
- self.get_bound::<Interface>(Vec::new(), None).await
+ Box::pin(async { self.get_bound::<Interface>(Vec::new(), None).await })
}
- /// Returns the type bound with `Interface` and the specified name.
- ///
- /// # Errors
- /// Will return `Err` if:
- /// - No binding for `Interface` with name `name` exists
- /// - Resolving the binding for `Interface` fails
- /// - Casting the binding for `Interface` fails
- pub async fn get_named<Interface>(
- self: &Arc<Self>,
+ fn get_named<'a, 'b, Interface>(
+ self: &'a Arc<Self>,
name: &'static str,
- ) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>
+ ) -> BoxFuture<'b, Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>>
where
- Interface: 'static + ?Sized + Send + Sync,
+ Interface: 'static + 'b + ?Sized + Send + Sync,
+ 'a: 'b,
+ Self: 'b,
{
- self.get_bound::<Interface>(Vec::new(), Some(name)).await
+ Box::pin(async { self.get_bound::<Interface>(Vec::new(), Some(name)).await })
}
- #[doc(hidden)]
- pub async fn get_bound<Interface>(
+ async fn get_bound<Interface>(
self: &Arc<Self>,
dependency_history: Vec<&'static str>,
name: Option<&'static str>,
@@ -140,10 +187,44 @@ impl AsyncDIContainer
self.handle_binding_providable(binding_providable).await
}
+}
+
+#[async_trait]
+impl details::DIContainerInternals for AsyncDIContainer
+{
+ async fn has_binding<Interface>(self: &Arc<Self>, name: Option<&'static str>) -> bool
+ where
+ Interface: ?Sized + 'static,
+ {
+ self.bindings.lock().await.has::<Interface>(name)
+ }
+
+ async fn set_binding<Interface>(
+ self: &Arc<Self>,
+ name: Option<&'static str>,
+ provider: Box<dyn IAsyncProvider<Self>>,
+ ) where
+ Interface: 'static + ?Sized,
+ {
+ self.bindings.lock().await.set::<Interface>(name, provider);
+ }
+ async fn remove_binding<Interface>(
+ self: &Arc<Self>,
+ name: Option<&'static str>,
+ ) -> Option<Box<dyn IAsyncProvider<Self>>>
+ where
+ Interface: 'static + ?Sized,
+ {
+ self.bindings.lock().await.remove::<Interface>(name)
+ }
+}
+
+impl AsyncDIContainer
+{
async fn handle_binding_providable<Interface>(
self: &Arc<Self>,
- binding_providable: AsyncProvidable,
+ binding_providable: AsyncProvidable<Self>,
) -> Result<SomeThreadsafePtr<Interface>, AsyncDIContainerError>
where
Interface: 'static + ?Sized + Send + Sync,
@@ -261,7 +342,7 @@ impl AsyncDIContainer
self: &Arc<Self>,
name: Option<&'static str>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, AsyncDIContainerError>
+ ) -> Result<AsyncProvidable<Self>, AsyncDIContainerError>
where
Interface: 'static + ?Sized + Send + Sync,
{
@@ -294,6 +375,40 @@ impl AsyncDIContainer
}
}
+pub(crate) mod details
+{
+ use std::sync::Arc;
+
+ use async_trait::async_trait;
+
+ use crate::provider::r#async::IAsyncProvider;
+
+ #[async_trait]
+ pub trait DIContainerInternals
+ {
+ async fn has_binding<Interface>(
+ self: &Arc<Self>,
+ name: Option<&'static str>,
+ ) -> bool
+ where
+ Interface: ?Sized + 'static;
+
+ async fn set_binding<Interface>(
+ self: &Arc<Self>,
+ name: Option<&'static str>,
+ provider: Box<dyn IAsyncProvider<Self>>,
+ ) where
+ Interface: 'static + ?Sized;
+
+ async fn remove_binding<Interface>(
+ self: &Arc<Self>,
+ name: Option<&'static str>,
+ ) -> Option<Box<dyn IAsyncProvider<Self>>>
+ where
+ Interface: 'static + ?Sized;
+ }
+}
+
#[cfg(test)]
mod tests
{
@@ -314,15 +429,15 @@ mod tests
Provider {}
#[async_trait]
- impl IAsyncProvider for Provider
+ impl IAsyncProvider<AsyncDIContainer> for Provider
{
async fn provide(
&self,
di_container: &Arc<AsyncDIContainer>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, InjectableError>;
+ ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>;
- fn do_clone(&self) -> Box<dyn IAsyncProvider>;
+ fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;
}
}
@@ -365,15 +480,15 @@ mod tests
Provider {}
#[async_trait]
- impl IAsyncProvider for Provider
+ impl IAsyncProvider<AsyncDIContainer> for Provider
{
async fn provide(
&self,
di_container: &Arc<AsyncDIContainer>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, InjectableError>;
+ ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>;
- fn do_clone(&self) -> Box<dyn IAsyncProvider>;
+ fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;
}
}
@@ -419,15 +534,15 @@ mod tests
Provider {}
#[async_trait]
- impl IAsyncProvider for Provider
+ impl IAsyncProvider<AsyncDIContainer> for Provider
{
async fn provide(
&self,
di_container: &Arc<AsyncDIContainer>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, InjectableError>;
+ ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>;
- fn do_clone(&self) -> Box<dyn IAsyncProvider>;
+ fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;
}
}
@@ -483,15 +598,15 @@ mod tests
Provider {}
#[async_trait]
- impl IAsyncProvider for Provider
+ impl IAsyncProvider<AsyncDIContainer> for Provider
{
async fn provide(
&self,
di_container: &Arc<AsyncDIContainer>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, InjectableError>;
+ ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>;
- fn do_clone(&self) -> Box<dyn IAsyncProvider>;
+ fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;
}
}
@@ -593,15 +708,15 @@ mod tests
Provider {}
#[async_trait]
- impl IAsyncProvider for Provider
+ impl IAsyncProvider<AsyncDIContainer> for Provider
{
async fn provide(
&self,
di_container: &Arc<AsyncDIContainer>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, InjectableError>;
+ ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>;
- fn do_clone(&self) -> Box<dyn IAsyncProvider>;
+ fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;
}
}
@@ -704,15 +819,15 @@ mod tests
Provider {}
#[async_trait]
- impl IAsyncProvider for Provider
+ impl IAsyncProvider<AsyncDIContainer> for Provider
{
async fn provide(
&self,
di_container: &Arc<AsyncDIContainer>,
dependency_history: Vec<&'static str>,
- ) -> Result<AsyncProvidable, InjectableError>;
+ ) -> Result<AsyncProvidable<AsyncDIContainer>, InjectableError>;
- fn do_clone(&self) -> Box<dyn IAsyncProvider>;
+ fn do_clone(&self) -> Box<dyn IAsyncProvider<AsyncDIContainer>>;
}
}