//! Syrette
//!
//! Syrette is a framework for utilizing inversion of control & dependency injection.
//!
//! # Example
//! ```
//! use std::error::Error;
//!
//! use syrette::di_container::blocking::prelude::*;
//! use syrette::injectable;
//! use syrette::ptr::TransientPtr;
//!
//! trait IWeapon
//! {
//! fn deal_damage(&self, damage: i32);
//! }
//!
//! struct Sword {}
//!
//! #[injectable(IWeapon)] // Makes Sword injectable with a interface of IWeapon
//! impl Sword
//! {
//! fn new() -> Self
//! {
//! Self {}
//! }
//! }
//!
//! impl IWeapon for Sword
//! {
//! fn deal_damage(&self, damage: i32)
//! {
//! println!("Sword dealt {} damage!", damage);
//! }
//! }
//!
//! trait IWarrior
//! {
//! fn fight(&self);
//! }
//!
//! struct Warrior
//! {
//! weapon: TransientPtr<dyn IWeapon>,
//! }
//!
//! #[injectable(IWarrior)] // Makes Warrior injectable with a interface of IWarrior
//! impl Warrior
//! {
//! fn new(weapon: TransientPtr<dyn IWeapon>) -> Self
//! {
//! Self { weapon }
//! }
//! }
//!
//! impl IWarrior for Warrior
//! {
//! fn fight(&self)
//! {
//! self.weapon.deal_damage(30);
//! }
//! }
//!
//! fn main() -> Result<(), Box<dyn Error>>
//! {
//! let mut di_container = DIContainer::new();
//!
//! // Creates a binding of the interface IWeapon to the concrete type Sword
//! di_container.bind::<dyn IWeapon>().to::<Sword>()?;
//!
//! // Creates a binding of the interface IWarrior to the concrete type Warrior
//! di_container.bind::<dyn IWarrior>().to::<Warrior>()?;
//!
//! // Create a transient IWarrior with all of its dependencies automatically injected
//! let warrior = di_container.get::<dyn IWarrior>()?.transient()?;
//!
//! warrior.fight();
//!
//! println!("Warrior has fighted");
//!
//! Ok(())
//! }
//! ```
pub use AsyncDIContainer;
pub use DIContainer;
pub use ;
pub use ;
/// Shortcut for creating a DI container binding for a injectable without a declared
/// interface.
///
/// This will declare a interface for the implementation.
///
/// Useful for when the implementation or the interface is generic.
///
/// # Arguments
/// {interface} => {implementation}, {DI container variable name}
///
/// # Examples
/// ```
/// # use syrette::{di_container_bind, DIContainer, injectable};
/// # use syrette::di_container::blocking::IDIContainer;
/// #
/// # trait INinja {}
/// #
/// # struct Ninja {}
/// #
/// # #[injectable]
/// # impl Ninja
/// # {
/// # fn new() -> Self
/// # {
/// # Self {}
/// # }
/// # }
/// #
/// # impl INinja for Ninja {}
/// #
/// let mut di_container = DIContainer::new();
///
/// di_container_bind!(INinja => Ninja, di_container);
/// ```
/// Creates a async closure.
///
/// # Examples
/// ```
/// # use syrette::async_closure;
/// #
/// # async fn do_heavy_operation(timeout: u32, size: u32) -> String { String::new() }
/// #
/// # async fn do_other_heavy_operation(input: String) -> String { String::new() }
/// #
/// async_closure!(|timeout, size| {
/// let value = do_heavy_operation(timeout, size).await;
///
/// let final_value = do_other_heavy_operation(value).await;
///
/// final_value
/// });
/// ```
///
/// expands to the following
///
/// ```rust
/// # async fn do_heavy_operation(timeout: u32, size: u32) -> String { String::new() }
/// #
/// # async fn do_other_heavy_operation(input: String) -> String { String::new() }
/// #
/// Box::new(|timeout, size| {
/// Box::pin(async move {
/// let value = do_heavy_operation(timeout, size).await;
///
/// let final_value = do_other_heavy_operation(value).await;
///
/// final_value
/// })
/// });
/// ```