diff options
| -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 +        ); +    } +}  | 
