From e381ae3b8649de47ba46925e402946658ac16d20 Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 15 Aug 2023 23:15:19 +0200 Subject: fix!: make the factory macro not change its input BREAKING CHANGE: The factory macro no longer - Changes the return type to be inside of a TransientPtr - Adds Send + Sync bounds when the threadsafe or the async flag is set - Changes the return type be inside of a BoxFuture when the async flag is set --- examples/async-factory/main.rs | 4 +- examples/async/interfaces/food.rs | 3 +- examples/factory/interfaces/user.rs | 4 +- macros/src/factory/type_alias.rs | 12 ++---- macros/src/lib.rs | 45 +++------------------- src/di_container/asynchronous/binding/builder.rs | 25 ++++++++---- src/di_container/asynchronous/mod.rs | 6 ++- src/di_container/blocking/binding/builder.rs | 7 ++-- src/di_container/blocking/mod.rs | 48 +++++++++--------------- 9 files changed, 62 insertions(+), 92 deletions(-) diff --git a/examples/async-factory/main.rs b/examples/async-factory/main.rs index 76efb2f..d368a32 100644 --- a/examples/async-factory/main.rs +++ b/examples/async-factory/main.rs @@ -6,6 +6,7 @@ use std::time::Duration; use anyhow::Result; use syrette::di_container::asynchronous::prelude::*; +use syrette::future::BoxFuture; use syrette::ptr::TransientPtr; use syrette::{declare_default_factory, factory}; use tokio::time::sleep; @@ -16,7 +17,8 @@ trait IFoo: Send + Sync } #[factory(async = true)] -type IFooFactory = dyn Fn(i32) -> dyn IFoo; +type IFooFactory = + dyn Fn(i32) -> BoxFuture<'static, TransientPtr> + Send + Sync; struct Foo { diff --git a/examples/async/interfaces/food.rs b/examples/async/interfaces/food.rs index e85519b..9d88083 100644 --- a/examples/async/interfaces/food.rs +++ b/examples/async/interfaces/food.rs @@ -1,4 +1,5 @@ use syrette::factory; +use syrette::ptr::TransientPtr; pub trait IFood: Send + Sync { @@ -6,4 +7,4 @@ pub trait IFood: Send + Sync } #[factory(threadsafe = true)] -pub type IFoodFactory = dyn Fn() -> dyn IFood; +pub type IFoodFactory = dyn Fn() -> TransientPtr + Send + Sync; diff --git a/examples/factory/interfaces/user.rs b/examples/factory/interfaces/user.rs index 75fbc87..aafd0cb 100644 --- a/examples/factory/interfaces/user.rs +++ b/examples/factory/interfaces/user.rs @@ -1,4 +1,5 @@ use syrette::factory; +use syrette::ptr::TransientPtr; pub trait IUser { @@ -8,4 +9,5 @@ pub trait IUser } #[factory] -pub type IUserFactory = dyn Fn(&'static str, &'static str, &'static str) -> dyn IUser; +pub type IUserFactory = + dyn Fn(&'static str, &'static str, &'static str) -> TransientPtr; diff --git a/macros/src/factory/type_alias.rs b/macros/src/factory/type_alias.rs index 790175b..fafcd54 100644 --- a/macros/src/factory/type_alias.rs +++ b/macros/src/factory/type_alias.rs @@ -1,7 +1,6 @@ use quote::ToTokens; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::{parse2, ItemType, Token, Type}; +use syn::{parse2, ItemType}; use crate::fn_trait::FnTrait; @@ -9,8 +8,6 @@ pub struct FactoryTypeAlias { pub type_alias: ItemType, pub factory_interface: FnTrait, - pub arg_types: Punctuated, - pub return_type: Type, } impl Parse for FactoryTypeAlias @@ -27,8 +24,6 @@ impl Parse for FactoryTypeAlias Ok(Self { type_alias, factory_interface: aliased_fn_trait.clone(), - arg_types: aliased_fn_trait.inputs, - return_type: aliased_fn_trait.output, }) } } @@ -39,8 +34,9 @@ mod tests use std::error::Error; use quote::{format_ident, quote}; + use syn::punctuated::Punctuated; use syn::token::And; - use syn::TypeReference; + use syn::{Type, TypeReference}; use super::*; use crate::test_utils; @@ -55,7 +51,7 @@ mod tests let factory_type_alias = parse2::(input_args)?; assert_eq!( - factory_type_alias.arg_types, + factory_type_alias.factory_interface.inputs, Punctuated::from_iter(vec![ test_utils::create_type(test_utils::create_path(&[ test_utils::create_path_segment(format_ident!("String"), &[]) diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 41001ae..c179b95 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -248,15 +248,12 @@ pub fn injectable(args_stream: TokenStream, input_stream: TokenStream) -> TokenS /// Makes a type alias usable as a factory interface. /// -/// The return type is automatically put inside of a [`TransientPtr`]. -/// /// # Arguments /// * (Zero or more) Flags. Like `a = true, b = false` /// /// # Flags /// - `threadsafe` - Mark as threadsafe. -/// - `async` - Mark as async. Infers the `threadsafe` flag. The return type is -/// automatically put inside of a pinned boxed future. +/// - `async` - Mark as async. Infers the `threadsafe` flag. /// /// # Examples /// ``` @@ -277,7 +274,7 @@ pub fn injectable(args_stream: TokenStream, input_stream: TokenStream) -> TokenS /// # impl IConfigurator for Configurator {} /// # /// #[factory] -/// type IConfiguratorFactory = dyn Fn(Vec) -> dyn IConfigurator; +/// type IConfiguratorFactory = dyn Fn(Vec) -> TransientPtr; /// ``` /// /// [`TransientPtr`]: https://docs.rs/syrette/latest/syrette/ptr/type.TransientPtr.html @@ -288,16 +285,11 @@ pub fn injectable(args_stream: TokenStream, input_stream: TokenStream) -> TokenS #[proc_macro_attribute] pub fn factory(args_stream: TokenStream, input_stream: TokenStream) -> TokenStream { - use quote::ToTokens; - use syn::{parse2, parse_str}; - use crate::factory::build_declare_interfaces::build_declare_factory_interfaces; use crate::factory::macro_args::FactoryMacroArgs; use crate::factory::type_alias::FactoryTypeAlias; - let input_stream: proc_macro2::TokenStream = input_stream.into(); - - set_dummy(input_stream.clone()); + set_dummy(input_stream.clone().into()); let FactoryMacroArgs { flags } = parse(args_stream).unwrap_or_abort(); @@ -318,34 +310,9 @@ pub fn factory(args_stream: TokenStream, input_stream: TokenStream) -> TokenStre } let FactoryTypeAlias { - mut type_alias, - mut factory_interface, - arg_types: _, - return_type: _, - } = parse2(input_stream).unwrap_or_abort(); - - let output = factory_interface.output.clone(); - - factory_interface.output = parse( - if is_async { - quote! { - syrette::future::BoxFuture<'static, syrette::ptr::TransientPtr<#output>> - } - } else { - quote! { - syrette::ptr::TransientPtr<#output> - } - } - .into(), - ) - .unwrap_or_abort(); - - if is_threadsafe { - factory_interface.add_trait_bound(parse_str("Send").unwrap_or_abort()); - factory_interface.add_trait_bound(parse_str("Sync").unwrap_or_abort()); - } - - type_alias.ty = Box::new(Type::Verbatim(factory_interface.to_token_stream())); + type_alias, + factory_interface, + } = parse(input_stream).unwrap_or_abort(); let decl_interfaces = build_declare_factory_interfaces(&factory_interface, is_threadsafe); diff --git a/src/di_container/asynchronous/binding/builder.rs b/src/di_container/asynchronous/binding/builder.rs index 45597e8..306d196 100644 --- a/src/di_container/asynchronous/binding/builder.rs +++ b/src/di_container/asynchronous/binding/builder.rs @@ -147,7 +147,7 @@ where /// # impl Foo for Bar {} /// # /// # #[factory(threadsafe = true)] - /// # type FooFactory = dyn Fn(i32, String) -> dyn Foo; + /// # type FooFactory = dyn Fn(i32, String) -> TransientPtr + Send + Sync; /// # /// # #[tokio::main] /// # async fn main() -> Result<(), Box> @@ -226,6 +226,7 @@ where /// # use syrette::{factory}; /// # use syrette::di_container::asynchronous::prelude::*; /// # use syrette::ptr::TransientPtr; + /// # use syrette::future::BoxFuture; /// # /// # trait Foo: Send + Sync {} /// # @@ -238,7 +239,10 @@ where /// # impl Foo for Bar {} /// # /// # #[factory(async = true)] - /// # type FooFactory = dyn Fn(i32, String) -> dyn Foo; + /// # type FooFactory = dyn Fn(i32, String) -> BoxFuture< + /// # 'static, + /// # TransientPtr + /// # > + Send + Sync; /// # /// # #[tokio::main] /// # async fn main() -> Result<(), Box> @@ -546,10 +550,12 @@ mod tests #[factory(threadsafe = true)] type IUserManagerFactory = dyn Fn( - String, - i32, - subjects_async::Number, - ) -> dyn subjects_async::IUserManager; + String, + i32, + subjects_async::Number, + ) -> TransientPtr + + Send + + Sync; let mut di_container_mock = mocks::async_di_container::MockAsyncDIContainer::new(); @@ -590,12 +596,17 @@ mod tests #[cfg(feature = "factory")] async fn can_bind_to_async_factory() -> Result<(), Box> { + use crate::future::BoxFuture; use crate::ptr::TransientPtr; use crate::test_utils::async_closure; use crate::{self as syrette, factory}; + #[rustfmt::skip] #[factory(async = true)] - type IUserManagerFactory = dyn Fn(String) -> dyn subjects_async::IUserManager; + type IUserManagerFactory = dyn Fn(String) -> BoxFuture< + 'static, + TransientPtr + > + Send + Sync; let mut di_container_mock = mocks::async_di_container::MockAsyncDIContainer::new(); diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs index 927f549..d330f4a 100644 --- a/src/di_container/asynchronous/mod.rs +++ b/src/di_container/asynchronous/mod.rs @@ -657,7 +657,8 @@ mod tests use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; #[crate::factory(threadsafe = true)] - type IUserManagerFactory = dyn Fn(Vec) -> dyn IUserManager; + type IUserManagerFactory = + dyn Fn(Vec) -> TransientPtr + Send + Sync; let di_container = AsyncDIContainer::new(); @@ -752,7 +753,8 @@ mod tests use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; #[crate::factory(threadsafe = true)] - type IUserManagerFactory = dyn Fn(Vec) -> dyn IUserManager; + type IUserManagerFactory = + dyn Fn(Vec) -> TransientPtr + Send + Sync; let di_container = AsyncDIContainer::new(); diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index 991961c..91855f5 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -151,10 +151,10 @@ where /// # impl ICustomer for Customer {} /// # /// # #[factory] - /// # type ICustomerFactory = dyn Fn(String, u32) -> dyn ICustomer; + /// # type ICustomerFactory = dyn Fn(String, u32) -> TransientPtr; /// # /// # #[factory] - /// # type ICustomerIDFactory = dyn Fn(u32) -> dyn ICustomerID; + /// # type ICustomerIDFactory = dyn Fn(u32) -> TransientPtr; /// # /// # fn main() -> Result<(), Box> /// # { @@ -354,7 +354,8 @@ mod tests use crate::ptr::TransientPtr; #[factory] - type IUserManagerFactory = dyn Fn(i32, String) -> dyn subjects::IUserManager; + type IUserManagerFactory = + dyn Fn(i32, String) -> TransientPtr; let mut mock_di_container = mocks::blocking_di_container::MockDIContainer::new(); diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index 5781583..aa89aad 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -493,28 +493,22 @@ mod tests } } - type FactoryFunc = dyn Fn< - (std::rc::Rc,), - Output = Box< - dyn Fn<(Vec,), Output = crate::ptr::TransientPtr>, - >, - >; - use crate as syrette; #[crate::factory] - type IUserManagerFactory = dyn Fn(Vec) -> dyn IUserManager; + type IUserManagerFactory = dyn Fn(Vec) -> TransientPtr; let di_container = DIContainer::new(); - let factory_func: &'static FactoryFunc = &|_: Rc| { - Box::new(move |users| { - let user_manager: TransientPtr = - TransientPtr::new(UserManager::new(users)); + let factory_func: &dyn Fn(Rc) -> Box = + &|_: Rc| { + Box::new(move |users| { + let user_manager: TransientPtr = + TransientPtr::new(UserManager::new(users)); - user_manager - }) - }; + user_manager + }) + }; let mut mock_provider = mocks::blocking_provider::MockProvider::new(); @@ -577,28 +571,22 @@ mod tests } } - type FactoryFunc = dyn Fn< - (std::rc::Rc,), - Output = Box< - dyn Fn<(Vec,), Output = crate::ptr::TransientPtr>, - >, - >; - use crate as syrette; #[crate::factory] - type IUserManagerFactory = dyn Fn(Vec) -> dyn IUserManager; + type IUserManagerFactory = dyn Fn(Vec) -> TransientPtr; let di_container = DIContainer::new(); - let factory_func: &'static FactoryFunc = &|_: Rc| { - Box::new(move |users| { - let user_manager: TransientPtr = - TransientPtr::new(UserManager::new(users)); + let factory_func: &dyn Fn(Rc) -> Box = + &|_: Rc| { + Box::new(move |users| { + let user_manager: TransientPtr = + TransientPtr::new(UserManager::new(users)); - user_manager - }) - }; + user_manager + }) + }; let mut mock_provider = mocks::blocking_provider::MockProvider::new(); -- cgit v1.2.3-18-g5258