diff options
author | HampusM <hampus@hampusmat.com> | 2022-08-20 17:08:58 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-08-21 18:17:50 +0200 |
commit | b31422d48a600ccccb682567f5eb11fc0bca547c (patch) | |
tree | fe3618522478249ef56c955e870e6525053f8ffa /src | |
parent | b749754dc1818a95e0baf0214b969fb99df4e7ab (diff) |
feat: allow bind interface to default factory
This commit will allow interface traits to be bound to default factories. Default factories being factories that doesn't take any arguments
Diffstat (limited to 'src')
-rw-r--r-- | src/di_container.rs | 44 | ||||
-rw-r--r-- | src/lib.rs | 67 |
2 files changed, 111 insertions, 0 deletions
diff --git a/src/di_container.rs b/src/di_container.rs index eaa0366..84fb9e0 100644 --- a/src/di_container.rs +++ b/src/di_container.rs @@ -181,6 +181,39 @@ where Ok(()) } + + /// Creates a binding of type `Interface` to a factory that takes no arguments + /// inside of the associated [`DIContainer`]. + /// + /// *This function is only available if Syrette is built with the "factory" feature.* + /// + /// # Errors + /// Will return Err if the associated [`DIContainer`] already have a binding for + /// the interface. + #[cfg(feature = "factory")] + pub fn to_default_factory<Return>( + &mut self, + factory_func: &'static dyn Fn<(), Output = TransientPtr<Return>>, + ) -> error_stack::Result<(), BindingBuilderError> + where + Return: 'static + ?Sized, + { + let factory_impl = CastableFactory::new(factory_func); + + self.di_container + .bindings + .set::<Interface>(Box::new(crate::provider::FactoryProvider::new( + crate::ptr::FactoryPtr::new(factory_impl), + ))) + .ok_or_else(|| { + report!(BindingBuilderError).attach_printable(format!( + "Binding already exists for interface '{}'", + type_name::<Interface>() + )) + })?; + + Ok(()) + } } /// Dependency injection container. @@ -290,6 +323,17 @@ impl DIContainer .map_err(unable_to_cast_binding::<Interface>); } + #[cfg(feature = "factory")] + if let Providable::Factory(binding_factory) = binding_providable { + use crate::interfaces::factory::IFactory; + + let factory = binding_factory + .cast::<dyn IFactory<(), Interface>>() + .map_err(unable_to_cast_binding::<Interface>)?; + + return Ok(factory()); + } + Err(report!(DIContainerError).attach_printable(format!( "Binding for interface '{}' is not transient", type_name::<Interface>() @@ -45,3 +45,70 @@ macro_rules! di_container_bind { syrette::declare_interface!($implementation -> $interface); }; } + +/// Shortcut for declaring a default factory. +/// +/// A default factory is a factory that doesn't take any arguments. +/// +/// More tedious ways to accomplish what this macro does would either be by using +/// the [`factory`] macro or by manually declaring the interfaces +/// with the [`declare_interface`] macro. +/// +/// *This macro is only available if Syrette is built with the "factory" feature.* +/// +/// # Arguments +/// - Interface trait +/// +/// # Examples +/// ``` +/// use syrette::declare_default_factory; +/// +/// trait IParser { +/// // Methods and etc here... +/// } +/// +/// declare_default_factory!(IParser); +/// ``` +/// +/// The expanded equivelent of this would be +/// +/// ``` +/// use syrette::declare_default_factory; +/// +/// trait IParser { +/// // Methods and etc here... +/// } +/// +/// syrette::declare_interface!( +/// syrette::castable_factory::CastableFactory< +/// (), +/// dyn IParser, +/// > -> syrette::interfaces::factory::IFactory<(), dyn IParser> +/// ); +/// +/// syrette::declare_interface!( +/// syrette::castable_factory::CastableFactory< +/// (), +/// dyn IParser, +/// > -> syrette::interfaces::any_factory::AnyFactory +/// ); +/// ``` +#[macro_export] +#[cfg(feature = "factory")] +macro_rules! declare_default_factory { + ($interface: path) => { + syrette::declare_interface!( + syrette::castable_factory::CastableFactory< + (), + dyn $interface, + > -> syrette::interfaces::factory::IFactory<(), dyn $interface> + ); + + syrette::declare_interface!( + syrette::castable_factory::CastableFactory< + (), + dyn $interface, + > -> syrette::interfaces::any_factory::AnyFactory + ); + } +} |