From 0f2756536e8fc311119da2af5b4dcc33f41bec6e Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 4 Oct 2023 12:51:06 +0200 Subject: refactor!: remove factory & declare_default_factory macros BREAKING CHANGE: The factory and the declare_default_factory macros have been removed. They are no longer needed to use factories --- examples/async-factory/main.rs | 5 +- examples/async/bootstrap.rs | 4 +- examples/async/interfaces/food.rs | 2 - examples/factory/interfaces/user.rs | 2 - examples/with-3rd-party/bootstrap.rs | 4 +- macros/src/factory/build_declare_interfaces.rs | 52 ----- macros/src/factory/declare_default_args.rs | 232 ----------------------- macros/src/factory/macro_args.rs | 106 ----------- macros/src/factory/mod.rs | 4 - macros/src/factory/type_alias.rs | 68 ------- macros/src/fn_trait.rs | 162 ---------------- macros/src/lib.rs | 158 --------------- src/any_factory.rs | 13 ++ src/castable_factory/mod.rs | 88 +++++++++ src/castable_factory/threadsafe.rs | 99 ++++++++++ src/di_container/asynchronous/binding/builder.rs | 27 +-- src/di_container/asynchronous/mod.rs | 89 +++------ src/di_container/blocking/binding/builder.rs | 18 +- src/di_container/blocking/mod.rs | 30 ++- src/lib.rs | 9 +- src/private/any_factory.rs | 11 -- src/private/castable_factory/mod.rs | 91 --------- src/private/castable_factory/threadsafe.rs | 103 ---------- src/private/factory.rs | 20 -- src/private/mod.rs | 9 - src/provider/async.rs | 31 +-- src/provider/blocking.rs | 20 +- 27 files changed, 287 insertions(+), 1170 deletions(-) delete mode 100644 macros/src/factory/build_declare_interfaces.rs delete mode 100644 macros/src/factory/declare_default_args.rs delete mode 100644 macros/src/factory/macro_args.rs delete mode 100644 macros/src/factory/mod.rs delete mode 100644 macros/src/factory/type_alias.rs delete mode 100644 macros/src/fn_trait.rs create mode 100644 src/any_factory.rs create mode 100644 src/castable_factory/mod.rs create mode 100644 src/castable_factory/threadsafe.rs delete mode 100644 src/private/any_factory.rs delete mode 100644 src/private/castable_factory/mod.rs delete mode 100644 src/private/castable_factory/threadsafe.rs delete mode 100644 src/private/factory.rs diff --git a/examples/async-factory/main.rs b/examples/async-factory/main.rs index 83f79f0..2b796cc 100644 --- a/examples/async-factory/main.rs +++ b/examples/async-factory/main.rs @@ -7,7 +7,7 @@ use std::time::Duration; use anyhow::Result; use syrette::future::BoxFuture; use syrette::ptr::TransientPtr; -use syrette::{declare_default_factory, factory, AsyncDIContainer}; +use syrette::AsyncDIContainer; use tokio::time::sleep; trait IFoo: Send + Sync @@ -15,7 +15,6 @@ trait IFoo: Send + Sync fn bar(&self); } -#[factory(threadsafe = true)] type IFooFactory = dyn Fn(i32) -> BoxFuture<'static, TransientPtr> + Send + Sync; @@ -68,8 +67,6 @@ impl IPerson for Person } } -declare_default_factory!(dyn IPerson, async = true); - #[tokio::main] async fn main() -> Result<()> { diff --git a/examples/async/bootstrap.rs b/examples/async/bootstrap.rs index 6fbe831..07e1bf8 100644 --- a/examples/async/bootstrap.rs +++ b/examples/async/bootstrap.rs @@ -1,5 +1,5 @@ use syrette::ptr::TransientPtr; -use syrette::{declare_default_factory, AsyncDIContainer}; +use syrette::AsyncDIContainer; use crate::animals::cat::Cat; use crate::animals::dog::Dog; @@ -10,8 +10,6 @@ use crate::interfaces::dog::IDog; use crate::interfaces::food::{IFood, IFoodFactory}; use crate::interfaces::human::IHuman; -declare_default_factory!(dyn ICat, threadsafe = true); - pub async fn bootstrap() -> Result { let mut di_container = AsyncDIContainer::new(); diff --git a/examples/async/interfaces/food.rs b/examples/async/interfaces/food.rs index 9d88083..21ea568 100644 --- a/examples/async/interfaces/food.rs +++ b/examples/async/interfaces/food.rs @@ -1,4 +1,3 @@ -use syrette::factory; use syrette::ptr::TransientPtr; pub trait IFood: Send + Sync @@ -6,5 +5,4 @@ pub trait IFood: Send + Sync fn eat(&self); } -#[factory(threadsafe = true)] pub type IFoodFactory = dyn Fn() -> TransientPtr + Send + Sync; diff --git a/examples/factory/interfaces/user.rs b/examples/factory/interfaces/user.rs index aafd0cb..5a60317 100644 --- a/examples/factory/interfaces/user.rs +++ b/examples/factory/interfaces/user.rs @@ -1,4 +1,3 @@ -use syrette::factory; use syrette::ptr::TransientPtr; pub trait IUser @@ -8,6 +7,5 @@ pub trait IUser fn get_password(&self) -> &'static str; } -#[factory] pub type IUserFactory = dyn Fn(&'static str, &'static str, &'static str) -> TransientPtr; diff --git a/examples/with-3rd-party/bootstrap.rs b/examples/with-3rd-party/bootstrap.rs index 5cd0f85..26386f5 100644 --- a/examples/with-3rd-party/bootstrap.rs +++ b/examples/with-3rd-party/bootstrap.rs @@ -1,14 +1,12 @@ use std::error::Error; use syrette::ptr::TransientPtr; -use syrette::{declare_default_factory, DIContainer}; +use syrette::DIContainer; use third_party_lib::Shuriken; use crate::interfaces::ninja::INinja; use crate::ninja::Ninja; -declare_default_factory!(Shuriken); - pub fn bootstrap() -> Result> { let mut di_container = DIContainer::new(); diff --git a/macros/src/factory/build_declare_interfaces.rs b/macros/src/factory/build_declare_interfaces.rs deleted file mode 100644 index 1e2d62e..0000000 --- a/macros/src/factory/build_declare_interfaces.rs +++ /dev/null @@ -1,52 +0,0 @@ -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::private::castable_factory::threadsafe::ThreadsafeCastableFactory< - #factory_interface, - syrette::di_container::asynchronous::AsyncDIContainer, - > -> syrette::private::factory::IThreadsafeFactory< - #factory_interface, - syrette::di_container::asynchronous::AsyncDIContainer, - >, - threadsafe_sharable = true - ); - - syrette::declare_interface!( - syrette::private::castable_factory::threadsafe::ThreadsafeCastableFactory< - #factory_interface, - syrette::di_container::asynchronous::AsyncDIContainer, - > -> syrette::private::any_factory::AnyThreadsafeFactory, - threadsafe_sharable = true - ); - } - } else { - quote! { - syrette::declare_interface!( - syrette::private::castable_factory::CastableFactory< - #factory_interface, - syrette::di_container::blocking::DIContainer - > -> syrette::private::factory::IFactory< - #factory_interface, - syrette::di_container::blocking::DIContainer - > - ); - - syrette::declare_interface!( - syrette::private::castable_factory::CastableFactory< - #factory_interface, - syrette::di_container::blocking::DIContainer - > -> syrette::private::any_factory::AnyFactory - ); - } - } -} diff --git a/macros/src/factory/declare_default_args.rs b/macros/src/factory/declare_default_args.rs deleted file mode 100644 index 9930f4f..0000000 --- a/macros/src/factory/declare_default_args.rs +++ /dev/null @@ -1,232 +0,0 @@ -use syn::parse::Parse; -use syn::punctuated::Punctuated; -use syn::{Token, Type}; - -use crate::macro_flag::MacroFlag; -use crate::util::iterator_ext::IteratorExt; - -pub const FACTORY_MACRO_FLAGS: &[&str] = &["threadsafe", "async"]; - -pub struct DeclareDefaultFactoryMacroArgs -{ - pub interface: Type, - pub flags: Punctuated, -} - -impl Parse for DeclareDefaultFactoryMacroArgs -{ - fn parse(input: syn::parse::ParseStream) -> syn::Result - { - let interface = input.parse()?; - - if !input.peek(Token![,]) { - return Ok(Self { - interface, - flags: Punctuated::new(), - }); - } - - input.parse::()?; - - let flags = Punctuated::::parse_terminated(input)?; - - for flag in &flags { - let name = flag.name().to_string(); - - if !FACTORY_MACRO_FLAGS.contains(&name.as_str()) { - return Err(input.error(format!( - "Unknown flag '{name}'. Expected one of [ {} ]", - FACTORY_MACRO_FLAGS.join(",") - ))); - } - } - - let flag_names = flags - .iter() - .map(|flag| flag.name().to_string()) - .collect::>(); - - if let Some((dupe_flag_name, _)) = flag_names.iter().find_duplicate() { - return Err(input.error(format!("Duplicate flag '{dupe_flag_name}'"))); - } - - Ok(Self { interface, flags }) - } -} - -#[cfg(test)] -mod tests -{ - use proc_macro2::Span; - use quote::{format_ident, quote}; - use syn::token::Dyn; - use syn::{ - parse2, - Lit, - LitBool, - Path, - PathArguments, - PathSegment, - TraitBound, - TraitBoundModifier, - Type, - TypeParamBound, - TypeTraitObject, - }; - - use super::*; - use crate::macro_flag::MacroFlagValue; - - #[test] - fn can_parse_with_interface_only() - { - let input_args = quote! { - dyn IFoo - }; - - let dec_def_fac_args = - parse2::(input_args).unwrap(); - - assert_eq!( - dec_def_fac_args.interface, - Type::TraitObject(TypeTraitObject { - dyn_token: Some(Dyn::default()), - bounds: Punctuated::from_iter(vec![TypeParamBound::Trait(TraitBound { - paren_token: None, - modifier: TraitBoundModifier::None, - lifetimes: None, - path: Path { - leading_colon: None, - segments: Punctuated::from_iter(vec![PathSegment { - ident: format_ident!("IFoo"), - arguments: PathArguments::None - }]) - } - })]) - }) - ); - - assert!(dec_def_fac_args.flags.is_empty()); - } - - #[test] - fn can_parse_with_interface_and_single_flag() - { - let input_args = quote! { - dyn IBar, threadsafe = true - }; - - let dec_def_fac_args = - parse2::(input_args).unwrap(); - - assert_eq!( - dec_def_fac_args.interface, - Type::TraitObject(TypeTraitObject { - dyn_token: Some(Dyn::default()), - bounds: Punctuated::from_iter(vec![TypeParamBound::Trait(TraitBound { - paren_token: None, - modifier: TraitBoundModifier::None, - lifetimes: None, - path: Path { - leading_colon: None, - segments: Punctuated::from_iter(vec![PathSegment { - ident: format_ident!("IBar"), - arguments: PathArguments::None - }]) - } - })]) - }) - ); - - assert_eq!( - dec_def_fac_args.flags, - Punctuated::from_iter(vec![MacroFlag { - name: format_ident!("threadsafe"), - value: MacroFlagValue::Literal(Lit::Bool(LitBool::new( - true, - Span::call_site() - ))) - }]) - ); - } - - #[test] - fn can_parse_with_interface_and_multiple_flags() - { - let input_args = quote! { - dyn IBar, threadsafe = true, async = false - }; - - let dec_def_fac_args = - parse2::(input_args).unwrap(); - - assert_eq!( - dec_def_fac_args.interface, - Type::TraitObject(TypeTraitObject { - dyn_token: Some(Dyn::default()), - bounds: Punctuated::from_iter(vec![TypeParamBound::Trait(TraitBound { - paren_token: None, - modifier: TraitBoundModifier::None, - lifetimes: None, - path: Path { - leading_colon: None, - segments: Punctuated::from_iter(vec![PathSegment { - ident: format_ident!("IBar"), - arguments: PathArguments::None - }]) - } - })]) - }) - ); - - assert_eq!( - dec_def_fac_args.flags, - Punctuated::from_iter(vec![ - MacroFlag { - name: format_ident!("threadsafe"), - value: MacroFlagValue::Literal(Lit::Bool(LitBool::new( - true, - Span::call_site() - ))) - }, - MacroFlag { - name: format_ident!("async"), - value: MacroFlagValue::Literal(Lit::Bool(LitBool::new( - false, - Span::call_site() - ))) - } - ]) - ); - } - - #[test] - fn cannot_parse_with_interface_and_invalid_flag() - { - let input_args = quote! { - dyn IBar, async = true, foo = false - }; - - assert!(parse2::(input_args).is_err()); - } - - #[test] - fn cannot_parse_with_interface_and_duplicate_flag() - { - assert!( - // Formatting is weird without this comment - parse2::(quote! { - dyn IBar, async = true, threadsafe = false, async = true - }) - .is_err() - ); - - assert!( - // Formatting is weird without this comment - parse2::(quote! { - dyn IBar, async = true, threadsafe = false, async = false - }) - .is_err() - ); - } -} diff --git a/macros/src/factory/macro_args.rs b/macros/src/factory/macro_args.rs deleted file mode 100644 index 676b412..0000000 --- a/macros/src/factory/macro_args.rs +++ /dev/null @@ -1,106 +0,0 @@ -use syn::parse::Parse; -use syn::punctuated::Punctuated; -use syn::Token; - -use crate::macro_flag::MacroFlag; -use crate::util::iterator_ext::IteratorExt; - -pub const FACTORY_MACRO_FLAGS: &[&str] = &["threadsafe"]; - -pub struct FactoryMacroArgs -{ - pub flags: Punctuated, -} - -impl Parse for FactoryMacroArgs -{ - fn parse(input: syn::parse::ParseStream) -> syn::Result - { - let flags = Punctuated::::parse_terminated(input)?; - - for flag in &flags { - let name = flag.name().to_string(); - - if !FACTORY_MACRO_FLAGS.contains(&name.as_str()) { - return Err(input.error(format!( - "Unknown flag '{}'. Expected one of [ {} ]", - name, - FACTORY_MACRO_FLAGS.join(",") - ))); - } - } - - let flag_names = flags - .iter() - .map(|flag| flag.name().to_string()) - .collect::>(); - - if let Some((dupe_flag_name, _)) = flag_names.iter().find_duplicate() { - return Err(input.error(format!("Duplicate flag '{dupe_flag_name}'"))); - } - - Ok(Self { flags }) - } -} - -#[cfg(test)] -mod tests -{ - use proc_macro2::Span; - use quote::{format_ident, quote}; - use syn::{parse2, Lit, LitBool}; - - use super::*; - use crate::macro_flag::MacroFlagValue; - - #[test] - fn can_parse_with_single_flag() - { - let input_args = quote! { - threadsafe = true - }; - - let factory_macro_args = parse2::(input_args).unwrap(); - - assert_eq!( - factory_macro_args.flags, - Punctuated::from_iter(vec![MacroFlag { - name: format_ident!("threadsafe"), - value: MacroFlagValue::Literal(Lit::Bool(LitBool::new( - true, - Span::call_site() - ))) - }]) - ); - } - - #[test] - fn cannot_parse_with_invalid_flag() - { - let input_args = quote! { - threadsafe = false, foo = true - }; - - assert!(parse2::(input_args).is_err()); - } - - #[test] - fn cannot_parse_with_duplicate_flag() - { - assert!( - // Formatting is weird without this comment - parse2::(quote! { - threadsafe = true, threadsafe = true - }) - .is_err() - ); - - assert!( - // Formatting is weird without this comment - parse2::(quote! { - threadsafe = true, threadsafe = false - }) - .is_err() - ); - } -} diff --git a/macros/src/factory/mod.rs b/macros/src/factory/mod.rs deleted file mode 100644 index 18bad8f..0000000 --- a/macros/src/factory/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod build_declare_interfaces; -pub mod declare_default_args; -pub mod macro_args; -pub mod type_alias; diff --git a/macros/src/factory/type_alias.rs b/macros/src/factory/type_alias.rs deleted file mode 100644 index cfa254f..0000000 --- a/macros/src/factory/type_alias.rs +++ /dev/null @@ -1,68 +0,0 @@ -use quote::ToTokens; -use syn::parse::{Parse, ParseStream}; -use syn::{parse2, ItemType}; - -use crate::fn_trait::FnTrait; - -pub struct FactoryTypeAlias -{ - pub type_alias: ItemType, - pub factory_interface: FnTrait, -} - -impl Parse for FactoryTypeAlias -{ - fn parse(input: ParseStream) -> syn::Result - { - let type_alias = input - .parse::() - .map_err(|_| input.error("Expected a type alias"))?; - - let aliased_fn_trait = - parse2::(type_alias.ty.as_ref().to_token_stream())?; - - Ok(Self { - type_alias, - factory_interface: aliased_fn_trait.clone(), - }) - } -} - -#[cfg(test)] -mod tests -{ - use quote::{format_ident, quote}; - use syn::punctuated::Punctuated; - use syn::token::And; - use syn::{Type, TypeReference}; - - use super::*; - use crate::test_utils; - - #[test] - fn can_parse() - { - let input_args = quote! { - type FooFactory = dyn Fn(String, &u32) -> Foo; - }; - - let factory_type_alias = parse2::(input_args).unwrap(); - - assert_eq!( - 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"), &[]) - ])), - Type::Reference(TypeReference { - and_token: And::default(), - lifetime: None, - mutability: None, - elem: Box::new(test_utils::create_type(test_utils::create_path(&[ - test_utils::create_path_segment(format_ident!("u32"), &[]) - ]))) - }) - ]) - ); - } -} diff --git a/macros/src/fn_trait.rs b/macros/src/fn_trait.rs deleted file mode 100644 index 0858cca..0000000 --- a/macros/src/fn_trait.rs +++ /dev/null @@ -1,162 +0,0 @@ -use quote::ToTokens; -use syn::parse::Parse; -use syn::punctuated::Punctuated; -use syn::token::Paren; -use syn::{parenthesized, Ident, Token, TraitBound, Type}; - -/// A function trait. `dyn Fn(u32) -> String` -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct FnTrait -{ - pub dyn_token: Token![dyn], - pub trait_ident: Ident, - pub paren_token: Paren, - pub inputs: Punctuated, - pub r_arrow_token: Token![->], - pub output: Type, - pub trait_bounds: Punctuated, -} - -impl FnTrait -{ - pub fn add_trait_bound(&mut self, trait_bound: TraitBound) - { - self.trait_bounds.push(trait_bound); - } -} - -impl Parse for FnTrait -{ - fn parse(input: syn::parse::ParseStream) -> syn::Result - { - let dyn_token = input.parse::()?; - - let trait_ident = input.parse::()?; - - if trait_ident.to_string().as_str() != "Fn" { - return Err(syn::Error::new(trait_ident.span(), "Expected 'Fn'")); - } - - let content; - - let paren_token = parenthesized!(content in input); - - let inputs = content.parse_terminated(Type::parse)?; - - let r_arrow_token = input.parse::]>()?; - - let output = input.parse::()?; - - Ok(Self { - dyn_token, - trait_ident, - paren_token, - inputs, - r_arrow_token, - output, - trait_bounds: Punctuated::new(), - }) - } -} - -impl ToTokens for FnTrait -{ - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) - { - self.dyn_token.to_tokens(tokens); - - self.trait_ident.to_tokens(tokens); - - self.paren_token.surround(tokens, |tokens_inner| { - self.inputs.to_tokens(tokens_inner); - }); - - self.r_arrow_token.to_tokens(tokens); - - self.output.to_tokens(tokens); - - if !self.trait_bounds.is_empty() { - let plus = ::default(); - - plus.to_tokens(tokens); - - self.trait_bounds.to_tokens(tokens); - } - } -} - -#[cfg(test)] -mod tests -{ - use quote::{format_ident, quote}; - use syn::token::{Dyn, RArrow}; - use syn::{parse2, PathSegment}; - - use super::*; - use crate::test_utils; - - #[test] - fn can_parse_fn_trait() - { - assert_eq!( - parse2::(quote! { - dyn Fn(String, u32) -> Handle - }) - .unwrap(), - FnTrait { - dyn_token: Dyn::default(), - trait_ident: format_ident!("Fn"), - paren_token: Paren::default(), - inputs: Punctuated::from_iter(vec![ - test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("String")) - ])), - test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("u32")) - ])) - ]), - r_arrow_token: RArrow::default(), - output: test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("Handle")) - ])), - trait_bounds: Punctuated::new() - } - ); - - assert!(parse2::(quote! { - Fn(u32) -> Handle - }) - .is_err()); - } - - #[test] - fn can_parse_fn_trait_to_tokens() - { - assert_eq!( - FnTrait { - dyn_token: Dyn::default(), - trait_ident: format_ident!("Fn"), - paren_token: Paren::default(), - inputs: Punctuated::from_iter(vec![ - test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("Bread")) - ])), - test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("Cheese")) - ])), - test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("Tomatoes")) - ])) - ]), - r_arrow_token: RArrow::default(), - output: test_utils::create_type(test_utils::create_path(&[ - PathSegment::from(format_ident!("Taco")) - ])), - trait_bounds: Punctuated::new() - } - .into_token_stream() - .to_string(), - "dyn Fn (Bread , Cheese , Tomatoes) -> Taco".to_string() - ); - } -} diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 7928e03..fa84e0e 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -35,12 +35,6 @@ mod injectable; mod macro_flag; mod util; -#[cfg(feature = "factory")] -mod factory; - -#[cfg(feature = "factory")] -mod fn_trait; - #[cfg(test)] mod test_utils; @@ -277,158 +271,6 @@ pub fn injectable(args_stream: TokenStream, input_stream: TokenStream) -> TokenS .into() } -/// Makes a type alias usable as a factory interface. -/// -/// # Arguments -/// * (Zero or more) Flags. Like `a = true, b = false` -/// -/// # Flags -/// - `threadsafe` - Mark as threadsafe. -/// -/// # Examples -/// ``` -/// # use syrette::factory; -/// # use syrette::ptr::TransientPtr; -/// # -/// # trait IConfigurator {} -/// # -/// # struct Configurator {} -/// # -/// # impl Configurator -/// # { -/// # fn new() -> Self -/// # { -/// # Self {} -/// # } -/// # } -/// # -/// # impl IConfigurator for Configurator {} -/// # -/// #[factory] -/// type IConfiguratorFactory = dyn Fn(Vec) -> TransientPtr; -/// ``` -/// -/// [`TransientPtr`]: https://docs.rs/syrette/latest/syrette/ptr/type.TransientPtr.html -#[cfg(feature = "factory")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))] -#[cfg(not(tarpaulin_include))] -#[proc_macro_error] -#[proc_macro_attribute] -pub fn factory(args_stream: TokenStream, input_stream: TokenStream) -> TokenStream -{ - use crate::factory::build_declare_interfaces::build_declare_factory_interfaces; - use crate::factory::macro_args::FactoryMacroArgs; - use crate::factory::type_alias::FactoryTypeAlias; - - set_dummy(input_stream.clone().into()); - - let FactoryMacroArgs { flags } = parse(args_stream).unwrap_or_abort(); - - let is_threadsafe = flags - .iter() - .find(|flag| flag.name() == "threadsafe") - .map_or(Ok(false), MacroFlag::get_bool) - .unwrap_or_abort(); - - let FactoryTypeAlias { - type_alias, - factory_interface, - } = parse(input_stream).unwrap_or_abort(); - - let decl_interfaces = - build_declare_factory_interfaces(&factory_interface, is_threadsafe); - - quote! { - #type_alias - - #decl_interfaces - } - .into() -} - -/// Shortcut for declaring a default factory. -/// -/// A default factory is a factory that doesn't take any arguments. -/// -/// Another way to accomplish what this macro does would be by using -/// the [`macro@factory`] macro. -/// -/// # Arguments -/// - Interface trait -/// * (Zero or more) Flags. Like `a = true, b = false` -/// -/// # Flags -/// - `threadsafe` - Mark as threadsafe. -/// - `async` - Mark as async. Infers the `threadsafe` flag. -/// -/// # Examples -/// ``` -/// # use syrette::declare_default_factory; -/// # -/// trait IParser -/// { -/// // Methods and etc here... -/// } -/// -/// declare_default_factory!(dyn IParser); -/// ``` -#[cfg(feature = "factory")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))] -#[cfg(not(tarpaulin_include))] -#[proc_macro_error] -#[proc_macro] -pub fn declare_default_factory(args_stream: TokenStream) -> TokenStream -{ - use syn::parse_str; - - 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_or_abort(); - - let mut is_threadsafe = flags - .iter() - .find(|flag| flag.name() == "threadsafe") - .map_or(Ok(false), MacroFlag::get_bool) - .unwrap_or_abort(); - - let is_async = flags - .iter() - .find(|flag| flag.name() == "async") - .map_or(Ok(false), MacroFlag::get_bool) - .unwrap_or_abort(); - - if is_async { - is_threadsafe = true; - } - - let mut factory_interface: FnTrait = parse( - if is_async { - quote! { - dyn Fn() -> syrette::future::BoxFuture< - 'static, - syrette::ptr::TransientPtr<#interface> - > - } - } else { - quote! { - dyn Fn() -> syrette::ptr::TransientPtr<#interface> - } - } - .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()); - } - - build_declare_factory_interfaces(&factory_interface, is_threadsafe).into() -} - /// Declares the interface trait of a implementation. /// /// # Arguments diff --git a/src/any_factory.rs b/src/any_factory.rs new file mode 100644 index 0000000..3aee98f --- /dev/null +++ b/src/any_factory.rs @@ -0,0 +1,13 @@ +//! Interface for any factory to ever exist. + +use std::any::Any; +use std::fmt::Debug; + +/// Interface for any factory to ever exist. +pub trait AnyFactory: Any + Debug +{ + fn as_any(&self) -> &dyn Any; +} + +/// Interface for any threadsafe factory to ever exist. +pub trait AnyThreadsafeFactory: AnyFactory + Send + Sync + Debug {} diff --git a/src/castable_factory/mod.rs b/src/castable_factory/mod.rs new file mode 100644 index 0000000..196dc14 --- /dev/null +++ b/src/castable_factory/mod.rs @@ -0,0 +1,88 @@ +use std::any::{type_name, Any}; +use std::fmt::Debug; + +use crate::any_factory::AnyFactory; +use crate::ptr::TransientPtr; + +#[cfg(feature = "async")] +pub mod threadsafe; + +pub struct CastableFactory +where + ReturnInterface: 'static + ?Sized, + DIContainerT: 'static, +{ + func: &'static dyn Fn(&DIContainerT) -> TransientPtr, +} + +impl CastableFactory +where + ReturnInterface: 'static + ?Sized, +{ + pub fn new( + func: &'static dyn Fn(&DIContainerT) -> TransientPtr, + ) -> Self + { + Self { func } + } + + pub fn call(&self, di_container: &DIContainerT) -> TransientPtr + { + (self.func)(di_container) + } +} + +impl AnyFactory + for CastableFactory +where + ReturnInterface: 'static + ?Sized, + DIContainerT: 'static, +{ + fn as_any(&self) -> &dyn Any + { + self + } +} + +impl Debug + for CastableFactory +where + ReturnInterface: 'static + ?Sized, +{ + #[cfg(not(tarpaulin_include))] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let ret = type_name::>(); + + formatter.write_fmt(format_args!( + "CastableFactory (&DIContainer) -> {ret} {{ ... }}" + )) + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + use crate::di_container::blocking::MockDIContainer; + + #[derive(Debug, PartialEq, Eq)] + struct Bacon + { + heal_amount: u32, + } + + #[test] + fn can_call() + { + let castable_factory = CastableFactory::new(&|_: &MockDIContainer| { + TransientPtr::new(Bacon { heal_amount: 27 }) + }); + + let mock_di_container = MockDIContainer::new(); + + let output = castable_factory.call(&mock_di_container); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); + } +} diff --git a/src/castable_factory/threadsafe.rs b/src/castable_factory/threadsafe.rs new file mode 100644 index 0000000..5935d75 --- /dev/null +++ b/src/castable_factory/threadsafe.rs @@ -0,0 +1,99 @@ +use std::any::{type_name, Any}; +use std::fmt::Debug; + +use crate::any_factory::{AnyFactory, AnyThreadsafeFactory}; +use crate::ptr::TransientPtr; + +pub struct ThreadsafeCastableFactory +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + func: &'static (dyn Fn(&DIContainerT) -> TransientPtr + Send + Sync), +} + +impl + ThreadsafeCastableFactory +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + pub fn new( + func: &'static (dyn Fn(&DIContainerT) -> TransientPtr + + Send + + Sync), + ) -> Self + { + Self { func } + } + + pub fn call(&self, di_container: &DIContainerT) -> TransientPtr + { + (self.func)(di_container) + } +} + +impl AnyFactory + for ThreadsafeCastableFactory +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + fn as_any(&self) -> &dyn Any + { + self + } +} + +impl AnyThreadsafeFactory + for ThreadsafeCastableFactory +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl Debug + for ThreadsafeCastableFactory +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + #[cfg(not(tarpaulin_include))] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let ret = type_name::>(); + + formatter.write_fmt(format_args!( + "ThreadsafeCastableFactory (&AsyncDIContainer) -> {ret} {{ ... }}", + )) + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + use crate::di_container::asynchronous::MockAsyncDIContainer; + + #[derive(Debug, PartialEq, Eq)] + struct Bacon + { + heal_amount: u32, + } + + #[test] + fn can_call() + { + let castable_factory = + ThreadsafeCastableFactory::new(&|_: &MockAsyncDIContainer| { + TransientPtr::new(Bacon { heal_amount: 27 }) + }); + + let mock_di_container = MockAsyncDIContainer::new(); + + let output = castable_factory.call(&mock_di_container); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); + } +} diff --git a/src/di_container/asynchronous/binding/builder.rs b/src/di_container/asynchronous/binding/builder.rs index 5e77c24..f42e6a1 100644 --- a/src/di_container/asynchronous/binding/builder.rs +++ b/src/di_container/asynchronous/binding/builder.rs @@ -127,7 +127,6 @@ where /// ``` /// # use std::error::Error; /// # - /// # use syrette::{factory}; /// # use syrette::AsyncDIContainer; /// # use syrette::ptr::TransientPtr; /// # @@ -141,7 +140,6 @@ where /// # /// # impl Foo for Bar {} /// # - /// # #[factory(threadsafe = true)] /// # type FooFactory = dyn Fn(i32, String) -> TransientPtr + Send + Sync; /// # /// # #[tokio::main] @@ -175,7 +173,7 @@ where Interface: Fn + Send + Sync, FactoryFunc: Fn(&AsyncDIContainer) -> BoxFn + Send + Sync, { - use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self @@ -213,7 +211,6 @@ where /// # use std::error::Error; /// # use std::time::Duration; /// # - /// # use syrette::{factory}; /// # use syrette::AsyncDIContainer; /// # use syrette::ptr::TransientPtr; /// # use syrette::future::BoxFuture; @@ -228,7 +225,6 @@ where /// # /// # impl Foo for Bar {} /// # - /// # #[factory] /// # type FooFactory = dyn Fn(i32, String) -> BoxFuture< /// # 'static, /// # TransientPtr @@ -274,7 +270,7 @@ where + Send + Sync, { - use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self @@ -358,7 +354,7 @@ where + Send + Sync, { - use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self @@ -449,7 +445,7 @@ where + Send + Sync, { - use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::provider::r#async::AsyncFactoryVariant; if self @@ -516,11 +512,8 @@ mod tests #[cfg(feature = "factory")] async fn can_bind_to_factory() { - use crate as syrette; - use crate::factory; use crate::ptr::TransientPtr; - #[factory(threadsafe = true)] type IUserManagerFactory = dyn Fn( String, i32, @@ -567,10 +560,8 @@ mod tests use crate::future::BoxFuture; use crate::ptr::TransientPtr; use crate::test_utils::async_closure; - use crate::{self as syrette, factory}; #[rustfmt::skip] - #[factory] type IUserManagerFactory = dyn Fn(String) -> BoxFuture< 'static, TransientPtr @@ -611,13 +602,8 @@ mod tests #[cfg(feature = "factory")] async fn can_bind_to_default_factory() { - use syrette_macros::declare_default_factory; - - use crate as syrette; use crate::ptr::TransientPtr; - declare_default_factory!(dyn subjects_async::IUserManager); - let mut di_container_mock = MockAsyncDIContainer::new(); di_container_mock @@ -654,13 +640,8 @@ mod tests #[cfg(feature = "factory")] async fn can_bind_to_async_default_factory() { - use syrette_macros::declare_default_factory; - use crate::ptr::TransientPtr; use crate::test_utils::async_closure; - use crate::{self as syrette}; - - declare_default_factory!(dyn subjects_async::IUserManager, async = true); let mut di_container_mock = MockAsyncDIContainer::new(); diff --git a/src/di_container/asynchronous/mod.rs b/src/di_container/asynchronous/mod.rs index 403ea18..3e29ef6 100644 --- a/src/di_container/asynchronous/mod.rs +++ b/src/di_container/asynchronous/mod.rs @@ -348,95 +348,64 @@ impl AsyncDIContainer } #[cfg(feature = "factory")] AsyncProvidable::Factory(factory_binding) => { - use crate::private::factory::IThreadsafeFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; let factory = factory_binding - .cast::>() - .map_err(|err| match err { - CastError::NotArcCastable(_) => { - AsyncDIContainerError::InterfaceNotAsync( - type_name::(), - ) - } - CastError::CastFailed { - source: _, - from: _, - to: _, - } - | CastError::GetCasterFailed(_) => { - AsyncDIContainerError::CastFailed { - interface: type_name::(), - binding_kind: "factory", - } - } + .as_any() + .downcast_ref::>() + .ok_or_else(|| AsyncDIContainerError::CastFailed { + interface: type_name::(), + binding_kind: "factory", })?; Ok(SomePtr::ThreadsafeFactory(factory.call(self).into())) } #[cfg(feature = "factory")] AsyncProvidable::DefaultFactory(binding) => { - use crate::private::factory::IThreadsafeFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::ptr::TransientPtr; - type DefaultFactoryFn = dyn IThreadsafeFactory< - dyn Fn<(), Output = TransientPtr> + Send + Sync, + type DefaultFactoryFn = ThreadsafeCastableFactory< + dyn Fn() -> TransientPtr + Send + Sync, AsyncDIContainer, >; - let default_factory = Self::cast_factory_binding::< - DefaultFactoryFn, - >(binding, "default factory")?; + let default_factory = binding + .as_any() + .downcast_ref::>() + .ok_or_else(|| AsyncDIContainerError::CastFailed { + interface: type_name::>(), + binding_kind: "default factory", + })?; Ok(SomePtr::Transient(default_factory.call(self)())) } #[cfg(feature = "factory")] AsyncProvidable::AsyncDefaultFactory(binding) => { + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; use crate::future::BoxFuture; - use crate::private::factory::IThreadsafeFactory; use crate::ptr::TransientPtr; - type AsyncDefaultFactoryFn = dyn IThreadsafeFactory< + type AsyncDefaultFactoryFn = ThreadsafeCastableFactory< dyn Fn<(), Output = BoxFuture<'static, TransientPtr>> + Send + Sync, AsyncDIContainer, >; - let async_default_factory = Self::cast_factory_binding::< - AsyncDefaultFactoryFn, - >( - binding, "async default factory" - )?; + let async_default_factory = binding + .as_any() + .downcast_ref::>() + .ok_or_else(|| AsyncDIContainerError::CastFailed { + interface: type_name::>(), + binding_kind: "async default factory", + })?; Ok(SomePtr::Transient(async_default_factory.call(self)().await)) } } } - #[cfg(feature = "factory")] - fn cast_factory_binding( - factory_binding: std::sync::Arc< - dyn crate::private::any_factory::AnyThreadsafeFactory, - >, - binding_kind: &'static str, - ) -> Result, AsyncDIContainerError> - { - factory_binding.cast::().map_err(|err| match err { - CastError::NotArcCastable(_) => { - AsyncDIContainerError::InterfaceNotAsync(type_name::()) - } - CastError::CastFailed { - source: _, - from: _, - to: _, - } - | CastError::GetCasterFailed(_) => AsyncDIContainerError::CastFailed { - interface: type_name::(), - binding_kind, - }, - }) - } - async fn get_binding_providable( &self, binding_options: BindingOptions<'static>, @@ -683,10 +652,8 @@ mod tests } } - use crate as syrette; - use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; - #[crate::factory(threadsafe = true)] type IUserManagerFactory = dyn Fn(Vec) -> TransientPtr + Send + Sync; @@ -767,10 +734,8 @@ mod tests } } - use crate as syrette; - use crate::private::castable_factory::threadsafe::ThreadsafeCastableFactory; + use crate::castable_factory::threadsafe::ThreadsafeCastableFactory; - #[crate::factory(threadsafe = true)] type IUserManagerFactory = dyn Fn(Vec) -> TransientPtr + Send + Sync; diff --git a/src/di_container/blocking/binding/builder.rs b/src/di_container/blocking/binding/builder.rs index f322809..9f7f6f9 100644 --- a/src/di_container/blocking/binding/builder.rs +++ b/src/di_container/blocking/binding/builder.rs @@ -119,7 +119,7 @@ where /// ``` /// # use std::error::Error; /// # - /// # use syrette::{DIContainer, factory}; + /// # use syrette::DIContainer; /// # use syrette::ptr::TransientPtr; /// # /// # trait ICustomerID {} @@ -140,10 +140,8 @@ where /// # /// # impl ICustomer for Customer {} /// # - /// # #[factory] /// # type ICustomerFactory = dyn Fn(String, u32) -> TransientPtr; /// # - /// # #[factory] /// # type ICustomerIDFactory = dyn Fn(u32) -> TransientPtr; /// # /// # fn main() -> Result<(), Box> @@ -183,7 +181,7 @@ where Interface: Fn>, Func: Fn(&DIContainer) -> Box, { - use crate::private::castable_factory::CastableFactory; + use crate::castable_factory::CastableFactory; if self .di_container @@ -218,7 +216,7 @@ where /// ``` /// # use std::error::Error; /// # - /// # use syrette::{DIContainer, factory}; + /// # use syrette::DIContainer; /// # use syrette::ptr::TransientPtr; /// # /// # trait IBuffer {} @@ -271,7 +269,7 @@ where dyn Fn<(), Output = crate::ptr::TransientPtr>, >, { - use crate::private::castable_factory::CastableFactory; + use crate::castable_factory::CastableFactory; if self .di_container @@ -335,11 +333,8 @@ mod tests #[cfg(feature = "factory")] fn can_bind_to_factory() { - use crate as syrette; - use crate::factory; use crate::ptr::TransientPtr; - #[factory] type IUserManagerFactory = dyn Fn(i32, String) -> TransientPtr; @@ -378,13 +373,8 @@ mod tests #[cfg(feature = "factory")] fn can_bind_to_default_factory() { - use syrette_macros::declare_default_factory; - - use crate as syrette; use crate::ptr::TransientPtr; - declare_default_factory!(dyn subjects::IUserManager); - let mut mock_di_container = MockDIContainer::new(); mock_di_container diff --git a/src/di_container/blocking/mod.rs b/src/di_container/blocking/mod.rs index 65e697e..d9efe94 100644 --- a/src/di_container/blocking/mod.rs +++ b/src/di_container/blocking/mod.rs @@ -285,11 +285,12 @@ impl DIContainer )), #[cfg(feature = "factory")] Providable::Factory(factory_binding) => { - use crate::private::factory::IFactory; + use crate::castable_factory::CastableFactory; let factory = factory_binding - .cast::>() - .map_err(|_| DIContainerError::CastFailed { + .as_any() + .downcast_ref::>() + .ok_or_else(|| DIContainerError::CastFailed { interface: type_name::(), binding_kind: "factory", })?; @@ -298,17 +299,16 @@ impl DIContainer } #[cfg(feature = "factory")] Providable::DefaultFactory(factory_binding) => { - use crate::private::factory::IFactory; + use crate::castable_factory::CastableFactory; use crate::ptr::TransientPtr; - type DefaultFactoryFn = dyn IFactory< - dyn Fn<(), Output = TransientPtr>, - DIContainer, - >; + type DefaultFactoryFn = + CastableFactory TransientPtr, DIContainer>; let default_factory = factory_binding - .cast::>() - .map_err(|_| DIContainerError::CastFailed { + .as_any() + .downcast_ref::>() + .ok_or_else(|| DIContainerError::CastFailed { interface: type_name::(), binding_kind: "default factory", })?; @@ -517,7 +517,7 @@ mod tests #[cfg(feature = "factory")] fn can_get_factory() { - use crate::private::castable_factory::CastableFactory; + use crate::castable_factory::CastableFactory; use crate::ptr::FactoryPtr; trait IUserManager @@ -556,9 +556,6 @@ mod tests } } - use crate as syrette; - - #[crate::factory] type IUserManagerFactory = dyn Fn(Vec) -> TransientPtr; let mut di_container = DIContainer::new(); @@ -595,7 +592,7 @@ mod tests #[cfg(feature = "factory")] fn can_get_factory_named() { - use crate::private::castable_factory::CastableFactory; + use crate::castable_factory::CastableFactory; use crate::ptr::FactoryPtr; trait IUserManager @@ -634,9 +631,6 @@ mod tests } } - use crate as syrette; - - #[crate::factory] type IUserManagerFactory = dyn Fn(Vec) -> TransientPtr; let mut di_container = DIContainer::new(); diff --git a/src/lib.rs b/src/lib.rs index 7f4738d..d93acc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,9 +102,6 @@ pub mod future; #[cfg_attr(doc_cfg, doc(cfg(feature = "async")))] pub use di_container::asynchronous::AsyncDIContainer; pub use di_container::blocking::DIContainer; -#[cfg(feature = "factory")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))] -pub use syrette_macros::{declare_default_factory, factory}; pub use syrette_macros::{declare_interface, injectable, named}; #[doc(hidden)] @@ -113,6 +110,12 @@ pub mod private; mod provider; mod util; +#[cfg(feature = "factory")] +mod castable_factory; + +#[cfg(feature = "factory")] +mod any_factory; + #[cfg(test)] #[cfg(not(tarpaulin_include))] mod test_utils; diff --git a/src/private/any_factory.rs b/src/private/any_factory.rs deleted file mode 100644 index 64af57e..0000000 --- a/src/private/any_factory.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Interface for any factory to ever exist. - -use std::fmt::Debug; - -use crate::private::cast::{CastFrom, CastFromArc}; - -/// Interface for any factory to ever exist. -pub trait AnyFactory: CastFrom + Debug {} - -/// Interface for any threadsafe factory to ever exist. -pub trait AnyThreadsafeFactory: CastFromArc + Debug {} diff --git a/src/private/castable_factory/mod.rs b/src/private/castable_factory/mod.rs deleted file mode 100644 index 2ac5918..0000000 --- a/src/private/castable_factory/mod.rs +++ /dev/null @@ -1,91 +0,0 @@ -use std::any::type_name; -use std::fmt::Debug; - -use crate::private::any_factory::AnyFactory; -use crate::private::factory::IFactory; -use crate::ptr::TransientPtr; - -#[cfg(feature = "async")] -pub mod threadsafe; - -pub struct CastableFactory -where - ReturnInterface: 'static + ?Sized, - DIContainerT: 'static, -{ - func: &'static dyn Fn(&DIContainerT) -> TransientPtr, -} - -impl CastableFactory -where - ReturnInterface: 'static + ?Sized, -{ - pub fn new( - func: &'static dyn Fn(&DIContainerT) -> TransientPtr, - ) -> Self - { - Self { func } - } -} - -impl IFactory - for CastableFactory -where - ReturnInterface: 'static + ?Sized, -{ - fn call(&self, di_container: &DIContainerT) -> TransientPtr - { - (self.func)(di_container) - } -} - -impl AnyFactory - for CastableFactory -where - ReturnInterface: 'static + ?Sized, - DIContainerT: 'static, -{ -} - -impl Debug - for CastableFactory -where - ReturnInterface: 'static + ?Sized, -{ - #[cfg(not(tarpaulin_include))] - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - let ret = type_name::>(); - - formatter.write_fmt(format_args!( - "CastableFactory (&DIContainer) -> {ret} {{ ... }}" - )) - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - use crate::di_container::blocking::MockDIContainer; - - #[derive(Debug, PartialEq, Eq)] - struct Bacon - { - heal_amount: u32, - } - - #[test] - fn can_call() - { - let castable_factory = CastableFactory::new(&|_: &MockDIContainer| { - TransientPtr::new(Bacon { heal_amount: 27 }) - }); - - let mock_di_container = MockDIContainer::new(); - - let output = castable_factory.call(&mock_di_container); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); - } -} diff --git a/src/private/castable_factory/threadsafe.rs b/src/private/castable_factory/threadsafe.rs deleted file mode 100644 index 6e8da42..0000000 --- a/src/private/castable_factory/threadsafe.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::any::type_name; -use std::fmt::Debug; - -use crate::private::any_factory::{AnyFactory, AnyThreadsafeFactory}; -use crate::private::factory::IThreadsafeFactory; -use crate::ptr::TransientPtr; - -pub struct ThreadsafeCastableFactory -where - DIContainerT: 'static, - ReturnInterface: 'static + ?Sized, -{ - func: &'static (dyn Fn(&DIContainerT) -> TransientPtr + Send + Sync), -} - -impl - ThreadsafeCastableFactory -where - DIContainerT: 'static, - ReturnInterface: 'static + ?Sized, -{ - pub fn new( - func: &'static (dyn Fn(&DIContainerT) -> TransientPtr - + Send - + Sync), - ) -> Self - { - Self { func } - } -} - -impl IThreadsafeFactory - for ThreadsafeCastableFactory -where - DIContainerT: 'static, - ReturnInterface: 'static + ?Sized, -{ - fn call(&self, di_container: &DIContainerT) -> TransientPtr - { - (self.func)(di_container) - } -} - -impl AnyFactory - for ThreadsafeCastableFactory -where - DIContainerT: 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl AnyThreadsafeFactory - for ThreadsafeCastableFactory -where - DIContainerT: 'static, - ReturnInterface: 'static + ?Sized, -{ -} - -impl Debug - for ThreadsafeCastableFactory -where - DIContainerT: 'static, - ReturnInterface: 'static + ?Sized, -{ - #[cfg(not(tarpaulin_include))] - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - let ret = type_name::>(); - - formatter.write_fmt(format_args!( - "ThreadsafeCastableFactory (&AsyncDIContainer) -> {ret} {{ ... }}", - )) - } -} - -#[cfg(test)] -mod tests -{ - use super::*; - use crate::di_container::asynchronous::MockAsyncDIContainer; - - #[derive(Debug, PartialEq, Eq)] - struct Bacon - { - heal_amount: u32, - } - - #[test] - fn can_call() - { - let castable_factory = - ThreadsafeCastableFactory::new(&|_: &MockAsyncDIContainer| { - TransientPtr::new(Bacon { heal_amount: 27 }) - }); - - let mock_di_container = MockAsyncDIContainer::new(); - - let output = castable_factory.call(&mock_di_container); - - assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); - } -} diff --git a/src/private/factory.rs b/src/private/factory.rs deleted file mode 100644 index 7191c2c..0000000 --- a/src/private/factory.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::private::cast::CastFrom; -use crate::ptr::TransientPtr; - -/// Interface for a factory. -pub trait IFactory: CastFrom -where - ReturnInterface: 'static + ?Sized, -{ - fn call(&self, di_container: &DIContainerT) -> TransientPtr; -} - -/// Interface for a threadsafe factory. -#[cfg(feature = "async")] -pub trait IThreadsafeFactory: - crate::private::cast::CastFromArc -where - ReturnInterface: 'static + ?Sized, -{ - fn call(&self, di_container: &DIContainerT) -> TransientPtr; -} diff --git a/src/private/mod.rs b/src/private/mod.rs index 8b20333..9b03ce8 100644 --- a/src/private/mod.rs +++ b/src/private/mod.rs @@ -4,12 +4,3 @@ pub mod cast; pub extern crate linkme; - -#[cfg(feature = "factory")] -pub mod any_factory; - -#[cfg(feature = "factory")] -pub mod factory; - -#[cfg(feature = "factory")] -pub mod castable_factory; diff --git a/src/provider/async.rs b/src/provider/async.rs index a3db57e..3875363 100644 --- a/src/provider/async.rs +++ b/src/provider/async.rs @@ -16,21 +16,15 @@ pub enum AsyncProvidable Singleton(ThreadsafeSingletonPtr>), #[cfg(feature = "factory")] Factory( - crate::ptr::ThreadsafeFactoryPtr< - dyn crate::private::any_factory::AnyThreadsafeFactory, - >, + crate::ptr::ThreadsafeFactoryPtr, ), #[cfg(feature = "factory")] DefaultFactory( - crate::ptr::ThreadsafeFactoryPtr< - dyn crate::private::any_factory::AnyThreadsafeFactory, - >, + crate::ptr::ThreadsafeFactoryPtr, ), #[cfg(feature = "factory")] AsyncDefaultFactory( - crate::ptr::ThreadsafeFactoryPtr< - dyn crate::private::any_factory::AnyThreadsafeFactory, - >, + crate::ptr::ThreadsafeFactoryPtr, ), } @@ -188,9 +182,8 @@ pub enum AsyncFactoryVariant #[cfg(feature = "factory")] pub struct AsyncFactoryProvider { - factory: crate::ptr::ThreadsafeFactoryPtr< - dyn crate::private::any_factory::AnyThreadsafeFactory, - >, + factory: + crate::ptr::ThreadsafeFactoryPtr, variant: AsyncFactoryVariant, } @@ -199,7 +192,7 @@ impl AsyncFactoryProvider { pub fn new( factory: crate::ptr::ThreadsafeFactoryPtr< - dyn crate::private::any_factory::AnyThreadsafeFactory, + dyn crate::any_factory::AnyThreadsafeFactory, >, variant: AsyncFactoryVariant, ) -> Self @@ -307,12 +300,22 @@ mod tests #[cfg(feature = "factory")] async fn async_factory_provider_works() { - use crate::private::any_factory::AnyThreadsafeFactory; + use std::any::Any; + + use crate::any_factory::{AnyFactory, AnyThreadsafeFactory}; use crate::ptr::ThreadsafeFactoryPtr; #[derive(Debug)] struct FooFactory; + impl AnyFactory for FooFactory + { + fn as_any(&self) -> &dyn Any + { + self + } + } + impl AnyThreadsafeFactory for FooFactory {} let factory_provider = AsyncFactoryProvider::new( diff --git a/src/provider/blocking.rs b/src/provider/blocking.rs index 5710a65..bde3be5 100644 --- a/src/provider/blocking.rs +++ b/src/provider/blocking.rs @@ -13,9 +13,9 @@ pub enum Providable Transient(TransientPtr>), Singleton(SingletonPtr>), #[cfg(feature = "factory")] - Factory(crate::ptr::FactoryPtr), + Factory(crate::ptr::FactoryPtr), #[cfg(feature = "factory")] - DefaultFactory(crate::ptr::FactoryPtr), + DefaultFactory(crate::ptr::FactoryPtr), } #[cfg_attr(test, mockall::automock)] @@ -108,7 +108,7 @@ where #[cfg(feature = "factory")] pub struct FactoryProvider { - factory: crate::ptr::FactoryPtr, + factory: crate::ptr::FactoryPtr, is_default_factory: bool, } @@ -116,7 +116,7 @@ pub struct FactoryProvider impl FactoryProvider { pub fn new( - factory: crate::ptr::FactoryPtr, + factory: crate::ptr::FactoryPtr, is_default_factory: bool, ) -> Self { @@ -196,13 +196,21 @@ mod tests #[cfg(feature = "factory")] fn factory_provider_works() { - use crate::private::any_factory::AnyFactory; + use std::any::Any; + + use crate::any_factory::AnyFactory; use crate::ptr::FactoryPtr; #[derive(Debug)] struct FooFactory; - impl AnyFactory for FooFactory {} + impl AnyFactory for FooFactory + { + fn as_any(&self) -> &dyn Any + { + self + } + } let factory_provider = FactoryProvider::new(FactoryPtr::new(FooFactory), false); let default_factory_provider = -- cgit v1.2.3-18-g5258