syrette/
lib.rs

1#![cfg_attr(feature = "factory", feature(unboxed_closures, tuple_trait))]
2#![cfg_attr(doc_cfg, feature(doc_cfg))]
3#![deny(clippy::all)]
4#![deny(clippy::pedantic)]
5#![allow(clippy::module_name_repetitions)]
6#![deny(missing_docs)]
7
8//! Syrette
9//!
10//! Syrette is a framework for utilizing inversion of control & dependency injection.
11//!
12//! # Example
13//! ```
14//! use std::error::Error;
15//!
16//! use syrette::ptr::TransientPtr;
17//! use syrette::{injectable, DIContainer};
18//!
19//! trait IWeapon
20//! {
21//!     fn deal_damage(&self, damage: i32);
22//! }
23//!
24//! struct Sword {}
25//!
26//! #[injectable(IWeapon)] // Makes Sword injectable with a interface of IWeapon
27//! impl Sword
28//! {
29//!     fn new() -> Self
30//!     {
31//!         Self {}
32//!     }
33//! }
34//!
35//! impl IWeapon for Sword
36//! {
37//!     fn deal_damage(&self, damage: i32)
38//!     {
39//!         println!("Sword dealt {} damage!", damage);
40//!     }
41//! }
42//!
43//! trait IWarrior
44//! {
45//!     fn fight(&self);
46//! }
47//!
48//! struct Warrior
49//! {
50//!     weapon: TransientPtr<dyn IWeapon>,
51//! }
52//!
53//! #[injectable(IWarrior)] // Makes Warrior injectable with a interface of IWarrior
54//! impl Warrior
55//! {
56//!     fn new(weapon: TransientPtr<dyn IWeapon>) -> Self
57//!     {
58//!         Self { weapon }
59//!     }
60//! }
61//!
62//! impl IWarrior for Warrior
63//! {
64//!     fn fight(&self)
65//!     {
66//!         self.weapon.deal_damage(30);
67//!     }
68//! }
69//!
70//! fn main() -> Result<(), Box<dyn Error>>
71//! {
72//!     let mut di_container = DIContainer::new();
73//!
74//!     // Creates a binding of the interface IWeapon to the concrete type Sword
75//!     di_container.bind::<dyn IWeapon>().to::<Sword>()?;
76//!
77//!     // Creates a binding of the interface IWarrior to the concrete type Warrior
78//!     di_container.bind::<dyn IWarrior>().to::<Warrior>()?;
79//!
80//!     // Create a transient IWarrior with all of its dependencies automatically injected
81//!     let warrior = di_container.get::<dyn IWarrior>()?.transient()?;
82//!
83//!     warrior.fight();
84//!
85//!     println!("Warrior has fighted");
86//!
87//!     Ok(())
88//! }
89//! ```
90
91pub mod dependency_history;
92pub mod di_container;
93pub mod errors;
94pub mod interfaces;
95pub mod ptr;
96
97#[cfg(feature = "async")]
98#[cfg_attr(doc_cfg, doc(cfg(feature = "async")))]
99pub mod future;
100
101#[cfg(feature = "async")]
102#[cfg_attr(doc_cfg, doc(cfg(feature = "async")))]
103pub use di_container::asynchronous::AsyncDIContainer;
104pub use di_container::blocking::DIContainer;
105#[cfg(feature = "factory")]
106#[cfg_attr(doc_cfg, doc(cfg(feature = "factory")))]
107pub use syrette_macros::{declare_default_factory, factory};
108pub use syrette_macros::{declare_interface, injectable, named};
109
110#[doc(hidden)]
111pub mod private;
112
113mod provider;
114mod util;
115
116#[cfg(test)]
117#[cfg(not(tarpaulin_include))]
118mod test_utils;
119
120/// Shortcut for creating a DI container binding for a injectable without a declared
121/// interface.
122///
123/// This will declare a interface for the implementation.
124///
125/// Useful for when the implementation or the interface is generic.
126///
127/// # Arguments
128/// {interface} => {implementation}, {DI container variable name}
129///
130/// # Examples
131/// ```
132/// # use syrette::{di_container_bind, DIContainer, injectable};
133/// #
134/// # trait INinja {}
135/// #
136/// # struct Ninja {}
137/// #
138/// # #[injectable]
139/// # impl Ninja
140/// # {
141/// #     fn new() -> Self
142/// #     {
143/// #         Self {}
144/// #     }
145/// # }
146/// #
147/// # impl INinja for Ninja {}
148/// #
149/// let mut di_container = DIContainer::new();
150///
151/// di_container_bind!(INinja => Ninja, di_container);
152/// ```
153#[cfg(not(tarpaulin_include))]
154#[macro_export]
155macro_rules! di_container_bind {
156    ($interface: path => $implementation: ty, $di_container: ident) => {
157        $di_container.bind::<dyn $interface>().to::<$implementation>().unwrap();
158
159        syrette::declare_interface!($implementation -> $interface);
160    };
161}