From 2a44ec3ffdcd78b23ac31b722b4312774d643c3a Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 24 Sep 2022 16:14:45 +0200 Subject: 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 --- examples/async/bootstrap.rs | 6 +- examples/with-3rd-party/bootstrap.rs | 2 +- macros/src/factory/build_declare_interfaces.rs | 52 ++++++++++++++ macros/src/factory/mod.rs | 1 + macros/src/lib.rs | 99 +++++--------------------- src/async_di_container.rs | 17 +++-- src/di_container.rs | 22 +++--- 7 files changed, 101 insertions(+), 98 deletions(-) create mode 100644 macros/src/factory/build_declare_interfaces.rs 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> di_container .bind::() .to_default_factory(&|_| { - let cat: TransientPtr = TransientPtr::new(Cat::new()); + Box::new(|| { + let cat: TransientPtr = 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, Box> di_container .bind::() - .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,), + #factory_interface + > -> syrette::interfaces::factory::IFactory< + (std::sync::Arc,), + #factory_interface + >, + async = true + ); + + syrette::declare_interface!( + syrette::castable_factory::threadsafe::ThreadsafeCastableFactory< + (std::sync::Arc,), + #factory_interface + > -> syrette::interfaces::any_factory::AnyThreadsafeFactory, + async = true + ); + } + } else { + quote! { + syrette::declare_interface!( + syrette::castable_factory::blocking::CastableFactory< + (std::rc::Rc,), + #factory_interface + > -> syrette::interfaces::factory::IFactory< + (std::rc::Rc,), + #factory_interface + > + ); + + syrette::declare_interface!( + syrette::castable_factory::blocking::CastableFactory< + (std::rc::Rc,), + #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,), - #factory_interface - > -> syrette::interfaces::factory::IFactory< - (std::sync::Arc,), - #factory_interface - >, - async = true - ); - - syrette::declare_interface!( - syrette::castable_factory::threadsafe::ThreadsafeCastableFactory< - (std::sync::Arc,), - #factory_interface - > -> syrette::interfaces::any_factory::AnyThreadsafeFactory, - async = true - ); - } - } else { - quote! { - syrette::declare_interface!( - syrette::castable_factory::blocking::CastableFactory< - (std::rc::Rc,), - #factory_interface - > -> syrette::interfaces::factory::IFactory< - (std::rc::Rc,), - #factory_interface - > - ); - - syrette::declare_interface!( - syrette::castable_factory::blocking::CastableFactory< - (std::rc::Rc,), - #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,), - #interface, - > -> syrette::interfaces::factory::IFactory< - (std::sync::Arc,), - #interface - >, - async = true - ); - - syrette::declare_interface!( - syrette::castable_factory::threadsafe::ThreadsafeCastableFactory< - (std::sync::Arc,), - #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,), - #interface, - > -> syrette::interfaces::factory::IFactory< - (std::rc::Rc,), - #interface - > - ); - - syrette::declare_interface!( - syrette::castable_factory::blocking::CastableFactory< - (std::rc::Rc,), - #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 @@ -361,8 +361,12 @@ where ) -> Result, AsyncBindingBuilderError> where Return: 'static + ?Sized, - FactoryFunc: Fn<(Arc,), Output = crate::ptr::TransientPtr> - + Send + FactoryFunc: Fn< + (Arc,), + Output = Box< + (dyn Fn<(), Output = crate::ptr::TransientPtr> + 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::,), Interface>>() + .cast::,), + dyn Fn<(), Output = TransientPtr> + 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 @@ -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( + pub fn to_default_factory( &self, - factory_func: &'static dyn Fn< - (Rc,), - Output = crate::ptr::TransientPtr, - >, + factory_func: &'static FactoryFunc, ) -> Result, BindingBuilderError> where Return: 'static + ?Sized, + FactoryFunc: Fn< + (Rc,), + Output = crate::ptr::TransientPtr< + dyn Fn<(), Output = crate::ptr::TransientPtr>, + >, + >, { { let bindings = self.di_container.bindings.borrow(); @@ -445,13 +448,16 @@ impl DIContainer use crate::interfaces::factory::IFactory; let default_factory = factory_binding - .cast::,), Interface>>() + .cast::,), + dyn Fn<(), Output = TransientPtr>, + >>() .map_err(|_| DIContainerError::CastFailed { interface: type_name::(), binding_kind: "default factory", })?; - Ok(SomePtr::Transient(default_factory(self.clone()))) + Ok(SomePtr::Transient(default_factory(self.clone())())) } } } -- cgit v1.2.3-18-g5258