aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/async_di_container.rs48
-rw-r--r--src/future.rs10
-rw-r--r--src/lib.rs51
3 files changed, 109 insertions, 0 deletions
diff --git a/src/async_di_container.rs b/src/async_di_container.rs
index 7dcca57..1ead116 100644
--- a/src/async_di_container.rs
+++ b/src/async_di_container.rs
@@ -294,6 +294,54 @@ where
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_factory<Args, Return, FactoryFunc>(
+ &self,
+ factory_func: &'static FactoryFunc,
+ ) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError>
+ where
+ Args: 'static,
+ Return: 'static + ?Sized,
+ Interface: Fn<Args, Output = crate::future::BoxFuture<'static, Return>>,
+ FactoryFunc: Fn<
+ (Arc<AsyncDIContainer>,),
+ Output = Box<
+ (dyn Fn<Args, Output = crate::future::BoxFuture<'static, Return>>),
+ >,
+ > + Send
+ + Sync,
+ {
+ 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),
+ false,
+ )),
+ );
+
+ Ok(AsyncBindingWhenConfigurator::new(self.di_container.clone()))
+ }
+
/// Creates a binding of type `Interface` to a factory that takes no arguments
/// inside of the associated [`AsyncDIContainer`].
///
diff --git a/src/future.rs b/src/future.rs
new file mode 100644
index 0000000..ae4b3a2
--- /dev/null
+++ b/src/future.rs
@@ -0,0 +1,10 @@
+//! Future related utilities.
+//!
+//! *This module is only available if Syrette is built with the "async" feature.*
+
+#![allow(clippy::module_name_repetitions)]
+use std::future::Future;
+use std::pin::Pin;
+
+/// A boxed future.
+pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
diff --git a/src/lib.rs b/src/lib.rs
index 2155350..247f907 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,6 +16,9 @@ pub mod ptr;
pub mod async_di_container;
#[cfg(feature = "async")]
+pub mod future;
+
+#[cfg(feature = "async")]
pub use async_di_container::AsyncDIContainer;
pub use di_container::DIContainer;
pub use syrette_macros::*;
@@ -75,3 +78,51 @@ macro_rules! di_container_bind {
syrette::declare_interface!($implementation -> $interface);
};
}
+
+/// Creates a async closure.
+///
+/// *This macro is only available if Syrette is built with the "async" feature.*
+///
+/// # Examples
+/// ```
+/// # use syrette::async_closure;
+/// #
+/// # async fn do_heavy_operation(timeout: u32, size: u32) -> String { String::new() }
+/// #
+/// # async fn do_other_heavy_operation(input: String) -> String { String::new() }
+/// #
+/// async_closure!(|timeout, size| {
+/// let value = do_heavy_operation(timeout, size).await;
+///
+/// let final_value = do_other_heavy_operation(value).await;
+///
+/// final_value
+/// });
+/// ```
+///
+/// expands to the following
+///
+/// ```rust
+/// # async fn do_heavy_operation(timeout: u32, size: u32) -> String { String::new() }
+/// #
+/// # async fn do_other_heavy_operation(input: String) -> String { String::new() }
+/// #
+/// Box::new(|timeout, size| {
+/// Box::pin(async move {
+/// let value = do_heavy_operation(timeout, size).await;
+///
+/// let final_value = do_other_heavy_operation(value).await;
+///
+/// final_value
+/// })
+/// });
+/// ```
+#[cfg(feature = "async")]
+#[macro_export]
+macro_rules! async_closure {
+ (|$($args: ident),*| { $($inner: stmt);* }) => {
+ Box::new(|$($args),*| {
+ Box::pin(async move { $($inner)* })
+ })
+ };
+}