aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-09-24 16:14:45 +0200
committerHampusM <hampus@hampusmat.com>2022-09-24 16:14:45 +0200
commit2a44ec3ffdcd78b23ac31b722b4312774d643c3a (patch)
treed3056a1fffe6311f863c4d683cc3444507c3e7d8
parent695f90bf900015df1e2728445f833dabced838a9 (diff)
refactor!: remove repetition of declaring factory interfaces
BREAKING CHANGE: The to_default_factory method of the blocking and async DI containers now expect a function returning another function
-rw-r--r--examples/async/bootstrap.rs6
-rw-r--r--examples/with-3rd-party/bootstrap.rs2
-rw-r--r--macros/src/factory/build_declare_interfaces.rs52
-rw-r--r--macros/src/factory/mod.rs1
-rw-r--r--macros/src/lib.rs99
-rw-r--r--src/async_di_container.rs17
-rw-r--r--src/di_container.rs22
7 files changed, 101 insertions, 98 deletions
diff --git a/examples/async/bootstrap.rs b/examples/async/bootstrap.rs
index 51af067..dd2febe 100644
--- a/examples/async/bootstrap.rs
+++ b/examples/async/bootstrap.rs
@@ -30,9 +30,11 @@ pub async fn bootstrap() -> Result<Arc<AsyncDIContainer>>
di_container
.bind::<dyn ICat>()
.to_default_factory(&|_| {
- let cat: TransientPtr<dyn ICat> = TransientPtr::new(Cat::new());
+ Box::new(|| {
+ let cat: TransientPtr<dyn ICat> = TransientPtr::new(Cat::new());
- cat
+ cat
+ })
})
.await?;
diff --git a/examples/with-3rd-party/bootstrap.rs b/examples/with-3rd-party/bootstrap.rs
index c5512c4..4fea754 100644
--- a/examples/with-3rd-party/bootstrap.rs
+++ b/examples/with-3rd-party/bootstrap.rs
@@ -18,7 +18,7 @@ pub fn bootstrap() -> Result<Rc<DIContainer>, Box<dyn Error>>
di_container
.bind::<Shuriken>()
- .to_default_factory(&|_| TransientPtr::new(Shuriken::new()))?;
+ .to_default_factory(&|_| Box::new(|| TransientPtr::new(Shuriken::new())))?;
Ok(di_container)
}
diff --git a/macros/src/factory/build_declare_interfaces.rs b/macros/src/factory/build_declare_interfaces.rs
new file mode 100644
index 0000000..ac4ddd6
--- /dev/null
+++ b/macros/src/factory/build_declare_interfaces.rs
@@ -0,0 +1,52 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+
+use crate::fn_trait::FnTrait;
+
+pub fn build_declare_factory_interfaces(
+ factory_interface: &FnTrait,
+ is_threadsafe: bool,
+) -> TokenStream
+{
+ if is_threadsafe {
+ quote! {
+ syrette::declare_interface!(
+ syrette::castable_factory::threadsafe::ThreadsafeCastableFactory<
+ (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
+ #factory_interface
+ > -> syrette::interfaces::factory::IFactory<
+ (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
+ #factory_interface
+ >,
+ async = true
+ );
+
+ syrette::declare_interface!(
+ syrette::castable_factory::threadsafe::ThreadsafeCastableFactory<
+ (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
+ #factory_interface
+ > -> syrette::interfaces::any_factory::AnyThreadsafeFactory,
+ async = true
+ );
+ }
+ } else {
+ quote! {
+ syrette::declare_interface!(
+ syrette::castable_factory::blocking::CastableFactory<
+ (std::rc::Rc<syrette::di_container::DIContainer>,),
+ #factory_interface
+ > -> syrette::interfaces::factory::IFactory<
+ (std::rc::Rc<syrette::di_container::DIContainer>,),
+ #factory_interface
+ >
+ );
+
+ syrette::declare_interface!(
+ syrette::castable_factory::blocking::CastableFactory<
+ (std::rc::Rc<syrette::di_container::DIContainer>,),
+ #factory_interface
+ > -> syrette::interfaces::any_factory::AnyFactory
+ );
+ }
+ }
+}
diff --git a/macros/src/factory/mod.rs b/macros/src/factory/mod.rs
index a8947c5..18bad8f 100644
--- a/macros/src/factory/mod.rs
+++ b/macros/src/factory/mod.rs
@@ -1,3 +1,4 @@
+pub mod build_declare_interfaces;
pub mod declare_default_args;
pub mod macro_args;
pub mod type_alias;
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index 390d239..07ee7a5 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -190,6 +190,7 @@ pub fn factory(args_stream: TokenStream, type_alias_stream: TokenStream) -> Toke
use quote::ToTokens;
use syn::Type;
+ use crate::factory::build_declare_interfaces::build_declare_factory_interfaces;
use crate::factory::macro_args::FactoryMacroArgs;
use crate::factory::type_alias::FactoryTypeAlias;
@@ -239,47 +240,8 @@ pub fn factory(args_stream: TokenStream, type_alias_stream: TokenStream) -> Toke
type_alias.ty = Box::new(Type::Verbatim(factory_interface.to_token_stream()));
- let decl_interfaces = if is_threadsafe {
- quote! {
- syrette::declare_interface!(
- syrette::castable_factory::threadsafe::ThreadsafeCastableFactory<
- (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
- #factory_interface
- > -> syrette::interfaces::factory::IFactory<
- (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
- #factory_interface
- >,
- async = true
- );
-
- syrette::declare_interface!(
- syrette::castable_factory::threadsafe::ThreadsafeCastableFactory<
- (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
- #factory_interface
- > -> syrette::interfaces::any_factory::AnyThreadsafeFactory,
- async = true
- );
- }
- } else {
- quote! {
- syrette::declare_interface!(
- syrette::castable_factory::blocking::CastableFactory<
- (std::rc::Rc<syrette::di_container::DIContainer>,),
- #factory_interface
- > -> syrette::interfaces::factory::IFactory<
- (std::rc::Rc<syrette::di_container::DIContainer>,),
- #factory_interface
- >
- );
-
- syrette::declare_interface!(
- syrette::castable_factory::blocking::CastableFactory<
- (std::rc::Rc<syrette::di_container::DIContainer>,),
- #factory_interface
- > -> syrette::interfaces::any_factory::AnyFactory
- );
- }
- };
+ let decl_interfaces =
+ build_declare_factory_interfaces(&factory_interface, is_threadsafe);
quote! {
#type_alias
@@ -293,7 +255,7 @@ pub fn factory(args_stream: TokenStream, type_alias_stream: TokenStream) -> Toke
///
/// A default factory is a factory that doesn't take any arguments.
///
-/// The more tedious way to accomplish what this macro does would be by using
+/// Another way to accomplish what this macro does would be by using
/// the [`macro@factory`] macro.
///
/// *This macro is only available if Syrette is built with the "factory" feature.*
@@ -323,7 +285,9 @@ pub fn factory(args_stream: TokenStream, type_alias_stream: TokenStream) -> Toke
#[cfg(feature = "factory")]
pub fn declare_default_factory(args_stream: TokenStream) -> TokenStream
{
+ use crate::factory::build_declare_interfaces::build_declare_factory_interfaces;
use crate::factory::declare_default_args::DeclareDefaultFactoryMacroArgs;
+ use crate::fn_trait::FnTrait;
let DeclareDefaultFactoryMacroArgs { interface, flags } = parse(args_stream).unwrap();
@@ -332,49 +296,20 @@ pub fn declare_default_factory(args_stream: TokenStream) -> TokenStream
.find(|flag| flag.flag.to_string().as_str() == "threadsafe")
.map_or(false, |flag| flag.is_on.value);
- if is_threadsafe {
- return quote! {
- syrette::declare_interface!(
- syrette::castable_factory::threadsafe::ThreadsafeCastableFactory<
- (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
- #interface,
- > -> syrette::interfaces::factory::IFactory<
- (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
- #interface
- >,
- async = true
- );
-
- syrette::declare_interface!(
- syrette::castable_factory::threadsafe::ThreadsafeCastableFactory<
- (std::sync::Arc<syrette::async_di_container::AsyncDIContainer>,),
- #interface,
- > -> syrette::interfaces::any_factory::AnyThreadsafeFactory,
- async = true
- );
+ let mut factory_interface: FnTrait = parse(
+ quote! {
+ dyn Fn() -> syrette::ptr::TransientPtr<#interface>
}
- .into();
- }
+ .into(),
+ )
+ .unwrap();
- quote! {
- syrette::declare_interface!(
- syrette::castable_factory::blocking::CastableFactory<
- (std::rc::Rc<syrette::di_container::DIContainer>,),
- #interface,
- > -> syrette::interfaces::factory::IFactory<
- (std::rc::Rc<syrette::di_container::DIContainer>,),
- #interface
- >
- );
-
- syrette::declare_interface!(
- syrette::castable_factory::blocking::CastableFactory<
- (std::rc::Rc<syrette::di_container::DIContainer>,),
- #interface,
- > -> syrette::interfaces::any_factory::AnyFactory
- );
+ if is_threadsafe {
+ factory_interface.add_trait_bound(parse_str("Send").unwrap());
+ factory_interface.add_trait_bound(parse_str("Sync").unwrap());
}
- .into()
+
+ build_declare_factory_interfaces(&factory_interface, is_threadsafe).into()
}
/// Declares the interface trait of a implementation.
diff --git a/src/async_di_container.rs b/src/async_di_container.rs
index c67900e..d90cc0b 100644
--- a/src/async_di_container.rs
+++ b/src/async_di_container.rs
@@ -78,7 +78,7 @@ use crate::provider::r#async::{
AsyncTransientTypeProvider,
IAsyncProvider,
};
-use crate::ptr::{SomeThreadsafePtr, ThreadsafeSingletonPtr};
+use crate::ptr::{SomeThreadsafePtr, ThreadsafeSingletonPtr, TransientPtr};
/// When configurator for a binding for type 'Interface' inside a [`AsyncDIContainer`].
pub struct AsyncBindingWhenConfigurator<Interface>
@@ -361,8 +361,12 @@ where
) -> Result<AsyncBindingWhenConfigurator<Interface>, AsyncBindingBuilderError>
where
Return: 'static + ?Sized,
- FactoryFunc: Fn<(Arc<AsyncDIContainer>,), Output = crate::ptr::TransientPtr<Return>>
- + Send
+ FactoryFunc: Fn<
+ (Arc<AsyncDIContainer>,),
+ Output = Box<
+ (dyn Fn<(), Output = crate::ptr::TransientPtr<Return>> + Send + Sync),
+ >,
+ > + Send
+ Sync,
{
let mut bindings_lock = self.di_container.bindings.lock().await;
@@ -531,7 +535,10 @@ impl AsyncDIContainer
use crate::interfaces::factory::IFactory;
let default_factory = default_factory_binding
- .cast::<dyn IFactory<(Arc<AsyncDIContainer>,), Interface>>()
+ .cast::<dyn IFactory<
+ (Arc<AsyncDIContainer>,),
+ dyn Fn<(), Output = TransientPtr<Interface>> + Send + Sync,
+ >>()
.map_err(|err| match err {
CastError::NotArcCastable(_) => {
AsyncDIContainerError::InterfaceNotAsync(
@@ -546,7 +553,7 @@ impl AsyncDIContainer
}
})?;
- Ok(SomeThreadsafePtr::Transient(default_factory(self.clone())))
+ Ok(SomeThreadsafePtr::Transient(default_factory(self.clone())()))
}
}
}
diff --git a/src/di_container.rs b/src/di_container.rs
index 2907969..45c3be8 100644
--- a/src/di_container.rs
+++ b/src/di_container.rs
@@ -71,7 +71,7 @@ use crate::provider::blocking::{
SingletonProvider,
TransientTypeProvider,
};
-use crate::ptr::{SingletonPtr, SomePtr};
+use crate::ptr::{SingletonPtr, SomePtr, TransientPtr};
/// When configurator for a binding for type 'Interface' inside a [`DIContainer`].
pub struct BindingWhenConfigurator<Interface>
@@ -294,15 +294,18 @@ where
/// Will return Err if the associated [`DIContainer`] already have a binding for
/// the interface.
#[cfg(feature = "factory")]
- pub fn to_default_factory<Return>(
+ pub fn to_default_factory<Return, FactoryFunc>(
&self,
- factory_func: &'static dyn Fn<
- (Rc<DIContainer>,),
- Output = crate::ptr::TransientPtr<Return>,
- >,
+ factory_func: &'static FactoryFunc,
) -> Result<BindingWhenConfigurator<Interface>, BindingBuilderError>
where
Return: 'static + ?Sized,
+ FactoryFunc: Fn<
+ (Rc<DIContainer>,),
+ Output = crate::ptr::TransientPtr<
+ dyn Fn<(), Output = crate::ptr::TransientPtr<Return>>,
+ >,
+ >,
{
{
let bindings = self.di_container.bindings.borrow();
@@ -445,13 +448,16 @@ impl DIContainer
use crate::interfaces::factory::IFactory;
let default_factory = factory_binding
- .cast::<dyn IFactory<(Rc<DIContainer>,), Interface>>()
+ .cast::<dyn IFactory<
+ (Rc<DIContainer>,),
+ dyn Fn<(), Output = TransientPtr<Interface>>,
+ >>()
.map_err(|_| DIContainerError::CastFailed {
interface: type_name::<Interface>(),
binding_kind: "default factory",
})?;
- Ok(SomePtr::Transient(default_factory(self.clone())))
+ Ok(SomePtr::Transient(default_factory(self.clone())()))
}
}
}