aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--syrette/src/di_container.rs14
-rw-r--r--syrette/src/lib.rs125
-rw-r--r--syrette_macros/src/lib.rs25
3 files changed, 161 insertions, 3 deletions
diff --git a/syrette/src/di_container.rs b/syrette/src/di_container.rs
index 7aa8225..f9580ae 100644
--- a/syrette/src/di_container.rs
+++ b/syrette/src/di_container.rs
@@ -11,6 +11,7 @@ use crate::injectable::Injectable;
use crate::libs::intertrait::cast_box::CastBox;
use crate::provider::{IInjectableTypeProvider, InjectableTypeProvider};
+/// Binding builder for `InterfaceTrait` in a [`DIContainer`].
pub struct BindingBuilder<'a, InterfaceTrait>
where
InterfaceTrait: 'static + ?Sized,
@@ -31,6 +32,8 @@ where
}
}
+ /// Creates a binding of `InterfaceTrait` to type `Implementation` inside of the
+ /// associated [`DIContainer`].
pub fn to<Implementation>(&mut self)
where
Implementation: Injectable,
@@ -57,6 +60,14 @@ impl Display for DIContainerError
impl Context for DIContainerError {}
+/// Dependency injection container.
+///
+/// # Examples
+/// ```
+/// di_container.bind::<dyn IDatabaseService>().to::<DatabaseService>();
+///
+/// let database_service = di_container.get::<dyn IDatabaseService>()?;
+/// ```
pub struct DIContainer
{
_bindings: HashMap<TypeId, Rc<dyn IInjectableTypeProvider>>,
@@ -64,6 +75,7 @@ pub struct DIContainer
impl<'a> DIContainer
{
+ /// Returns a new `DIContainer`.
pub fn new() -> Self
{
Self {
@@ -71,6 +83,7 @@ impl<'a> DIContainer
}
}
+ /// Returns a new [`BindingBuilder`] for the given interface trait.
pub fn bind<InterfaceTrait>(&'a mut self) -> BindingBuilder<InterfaceTrait>
where
InterfaceTrait: 'static + ?Sized,
@@ -78,6 +91,7 @@ impl<'a> DIContainer
BindingBuilder::<InterfaceTrait>::new(self)
}
+ /// Returns the value bound with `InterfaceTrait`.
pub fn get<InterfaceTrait>(
&self,
) -> error_stack::Result<Box<InterfaceTrait>, DIContainerError>
diff --git a/syrette/src/lib.rs b/syrette/src/lib.rs
index 5cf9f71..fb5d03f 100644
--- a/syrette/src/lib.rs
+++ b/syrette/src/lib.rs
@@ -1,8 +1,127 @@
-mod di_container;
+//! Syrette
+//!
+//! Syrette is a collection of utilities useful for performing dependency injection.
+//!
+//! # Examples
+//! ```
+//! use syrette::{injectable, DIContainer, DIContainerError};
+//!
+//! trait IDog
+//! {
+//! fn woof(&self);
+//! }
+//!
+//! struct Dog {}
+//!
+//! #[injectable(IDog)]
+//! impl Dog
+//! {
+//! fn new() -> Self
+//! {
+//! Self {}
+//! }
+//! }
+//!
+//! impl IDog for Dog
+//! {
+//! fn woof(&self)
+//! {
+//! println!("Woof!");
+//! }
+//! }
+//!
+//! trait ICat
+//! {
+//! fn meow(&self);
+//! }
+//!
+//! struct Cat {}
+//!
+//! #[injectable(ICat)]
+//! impl Cat
+//! {
+//! fn new() -> Self
+//! {
+//! Self {}
+//! }
+//! }
+//!
+//! impl ICat for Cat
+//! {
+//! fn meow(&self)
+//! {
+//! println!("Meow!");
+//! }
+//! }
+//!
+//! trait IHuman
+//! {
+//! fn make_pets_make_sounds(&self);
+//! }
+//!
+//! struct Human
+//! {
+//! _dog: Box<dyn IDog>,
+//! _cat: Box<dyn ICat>,
+//! }
+//!
+//! #[injectable(IHuman)]
+//! impl Human
+//! {
+//! fn new(dog: Box<dyn IDog>, cat: Box<dyn ICat>) -> Self
+//! {
+//! Self {
+//! _dog: dog,
+//! _cat: cat,
+//! }
+//! }
+//! }
+//!
+//! impl IHuman for Human
+//! {
+//! fn make_pets_make_sounds(&self)
+//! {
+//! println!("Hi doggy!");
+//!
+//! self._dog.woof();
+//!
+//! println!("Hi kitty!");
+//!
+//! self._cat.meow();
+//! }
+//! }
+//!
+//! fn main() -> error_stack::Result<(), DIContainerError>
+//! {
+//! println!("Hello, world!");
+//!
+//! let mut di_container: DIContainer = DIContainer::new();
+//!
+//! di_container.bind::<dyn IDog>().to::<Dog>();
+//! di_container.bind::<dyn ICat>().to::<Cat>();
+//! di_container.bind::<dyn IHuman>().to::<Human>();
+//!
+//! let dog = di_container.get::<dyn IDog>()?;
+//!
+//! dog.woof();
+//!
+//! let human = di_container.get::<dyn IHuman>()?;
+//!
+//! human.make_pets_make_sounds();
+//!
+//! Ok(())
+//! }
+//!
+//! ```
+
+pub mod di_container;
+pub mod injectable;
pub use di_container::*;
pub use syrette_macros::*;
-pub mod injectable;
-
+#[doc(hidden)]
pub mod libs;
+
+// Private
+mod provider;
diff --git a/syrette_macros/src/lib.rs b/syrette_macros/src/lib.rs
index 3fd8a59..faf338c 100644
--- a/syrette_macros/src/lib.rs
+++ b/syrette_macros/src/lib.rs
@@ -141,6 +141,30 @@ fn get_dependency_types(item_impl: &ItemImpl) -> Vec<Type>
);
}
+/// Makes a struct injectable. Therefore usable with `DIContainer`.
+///
+/// # Arguments
+///
+/// * A interface trait the struct implements.
+///
+/// # Examples
+/// ```
+/// trait IConfigReader
+/// {
+/// fn read_config() -> Config;
+/// }
+///
+/// struct ConfigReader {}
+///
+/// #[injectable(IConfigReader)]
+/// impl IConfigReader for ConfigReader
+/// {
+/// fn read_config() -> Config
+/// {
+/// // Stuff here
+/// }
+/// }
+/// ```
#[proc_macro_attribute]
pub fn injectable(args_stream: TokenStream, impl_stream: TokenStream) -> TokenStream
{
@@ -205,6 +229,7 @@ pub fn injectable(args_stream: TokenStream, impl_stream: TokenStream) -> TokenSt
.into()
}
+#[doc(hidden)]
#[proc_macro]
pub fn castable_to(input: TokenStream) -> TokenStream
{