diff options
-rw-r--r-- | macros/Cargo.toml | 2 | ||||
-rw-r--r-- | macros/src/lib.rs | 76 | ||||
-rw-r--r-- | src/di_container.rs | 91 | ||||
-rw-r--r-- | src/errors/di_container.rs | 4 | ||||
-rw-r--r-- | src/errors/injectable.rs | 3 | ||||
-rw-r--r-- | src/errors/mod.rs | 2 | ||||
-rw-r--r-- | src/interfaces/any_factory.rs | 3 | ||||
-rw-r--r-- | src/interfaces/factory.rs | 11 | ||||
-rw-r--r-- | src/interfaces/injectable.rs | 2 | ||||
-rw-r--r-- | src/interfaces/mod.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/ptr.rs | 5 |
12 files changed, 155 insertions, 47 deletions
diff --git a/macros/Cargo.toml b/macros/Cargo.toml index d806396..d9392e6 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -17,3 +17,5 @@ quote = "1.0.18" proc-macro2 = "1.0.40" uuid = { version = "0.8", features = ["v4"] } +[dev_dependencies] +syrette = { version = "0.2.0", path = "..", features = ["factory"] } diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 20eb7d3..aca4007 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,5 +1,8 @@ #![deny(clippy::all)] #![deny(clippy::pedantic)] +#![deny(missing_docs)] + +//! Macros for the [Syrette](https://crates.io/crates/syrette) crate. use proc_macro::TokenStream; use quote::quote; @@ -27,8 +30,26 @@ use libs::intertrait_macros::gen_caster::generate_caster; /// /// # Important /// If the interface trait argument is excluded, you should either manually -/// declare the interface with the `declare_interface` macro or use -/// the `di_container_bind` macro to create a DI container binding. +/// declare the interface with the [`declare_interface!`] macro or use +/// the [`di_container_bind`] macro to create a DI container binding. +/// +/// # Example +/// ``` +/// use syrette::injectable; +/// +/// struct PasswordManager {} +/// +/// #[injectable] +/// impl PasswordManager { +/// pub fn new() -> Self { +/// Self {} +/// } +/// } +/// ``` +/// +/// [`DIContainer`]: ../syrette/di_container/struct.DIContainer.html +/// [`Injectable`]: ../syrette/interfaces/injectable/trait.Injectable.html +/// [`di_container_bind`]: ../syrette/macro.di_container_bind.html #[proc_macro_attribute] pub fn injectable(args_stream: TokenStream, impl_stream: TokenStream) -> TokenStream { @@ -62,6 +83,57 @@ pub fn injectable(args_stream: TokenStream, impl_stream: TokenStream) -> TokenSt /// /// # Panics /// If the attributed item is not a type alias. +/// +/// # Examples +/// ``` +/// use std::collections::HashMap; +/// +/// use syrette::interfaces::factory::IFactory; +/// use syrette::factory; +/// +/// enum ConfigValue +/// { +/// String(String), +/// Bool(bool), +/// Int(i32), +/// None, +/// } +/// +/// trait IConfigurator +/// { +/// fn configure(&self, key: String, value: ConfigValue); +/// } +/// +/// struct Configurator { +/// config: HashMap<String, ConfigValue>, +/// } +/// +/// impl Configurator +/// { +/// fn new(keys: Vec<String>) -> Self +/// { +/// Self { +/// config: HashMap::from( +/// keys +/// .iter() +/// .map(|key| (key.clone(), ConfigValue::None)) +/// .collect::<HashMap<_, _>>() +/// ) +/// } +/// } +/// } +/// +/// impl IConfigurator for Configurator +/// { +/// fn configure(&self, key: String, value: ConfigValue) +/// { +/// // ... +/// } +/// } +/// +/// #[factory] +/// type IConfiguratorFactory = dyn IFactory<(Vec<String>,), dyn IConfigurator>; +/// ``` #[proc_macro_attribute] pub fn factory(_: TokenStream, type_alias_stream: TokenStream) -> TokenStream { diff --git a/src/di_container.rs b/src/di_container.rs index e18fc3a..89bbcd1 100644 --- a/src/di_container.rs +++ b/src/di_container.rs @@ -1,3 +1,48 @@ +//! Dependency injection container and other related utilities. +/// +/// # Examples +/// ``` +/// use std::collections::HashMap; +/// +/// use syrette::{DIContainer, injectable}; +/// use syrette::errors::di_container::DIContainerError; +/// +/// trait IDatabaseService +/// { +/// fn get_all_records(&self, table_name: String) -> HashMap<String, String>; +/// } +/// +/// struct DatabaseService {} +/// +/// #[injectable(IDatabaseService)] +/// impl DatabaseService +/// { +/// fn new() -> Self +/// { +/// Self {} +/// } +/// } +/// +/// impl IDatabaseService for DatabaseService +/// { +/// fn get_all_records(&self, table_name: String) -> HashMap<String, String> +/// { +/// // Do stuff here +/// HashMap::<String, String>::new() +/// } +/// } +/// +/// fn main() -> error_stack::Result<(), DIContainerError> +/// { +/// let mut di_container = DIContainer::new(); +/// +/// di_container.bind::<dyn IDatabaseService>().to::<DatabaseService>(); +/// +/// let database_service = di_container.get::<dyn IDatabaseService>()?; +/// +/// Ok(()) +/// } +/// ``` use std::any::type_name; use std::marker::PhantomData; @@ -101,50 +146,6 @@ where } /// Dependency injection container. -/// -/// # Examples -/// ``` -/// use std::collections::HashMap; -/// -/// use syrette::{DIContainer, injectable}; -/// use syrette::errors::di_container::DIContainerError; -/// -/// trait IDatabaseService -/// { -/// fn get_all_records(&self, table_name: String) -> HashMap<String, String>; -/// } -/// -/// struct DatabaseService {} -/// -/// #[injectable(IDatabaseService)] -/// impl DatabaseService -/// { -/// fn new() -> Self -/// { -/// Self {} -/// } -/// } -/// -/// impl IDatabaseService for DatabaseService -/// { -/// fn get_all_records(&self, table_name: String) -> HashMap<String, String> -/// { -/// // Do stuff here -/// HashMap::<String, String>::new() -/// } -/// } -/// -/// fn main() -> error_stack::Result<(), DIContainerError> -/// { -/// let mut di_container = DIContainer::new(); -/// -/// di_container.bind::<dyn IDatabaseService>().to::<DatabaseService>(); -/// -/// let database_service = di_container.get::<dyn IDatabaseService>()?; -/// -/// Ok(()) -/// } -/// ``` pub struct DIContainer { bindings: DIContainerBindingMap, @@ -176,7 +177,7 @@ impl DIContainer /// - No binding for `Interface` exists /// - Resolving the binding for `Interface` fails /// - Casting the binding for `Interface` fails - /// - The binding for `Interface` is not injectable + /// - The binding for `Interface` is not transient pub fn get<Interface>( &self, ) -> error_stack::Result<TransientPtr<Interface>, DIContainerError> diff --git a/src/errors/di_container.rs b/src/errors/di_container.rs index 3b8c717..127676f 100644 --- a/src/errors/di_container.rs +++ b/src/errors/di_container.rs @@ -1,8 +1,11 @@ +//! Error types for the DI container. + use std::fmt; use std::fmt::{Display, Formatter}; use error_stack::Context; +/// Error for when the DI container fails to do something. #[derive(Debug)] pub struct DIContainerError; @@ -16,6 +19,7 @@ impl Display for DIContainerError impl Context for DIContainerError {} +/// Error for when the binding builder fails to do something. #[derive(Debug)] pub struct BindingBuilderError; diff --git a/src/errors/injectable.rs b/src/errors/injectable.rs index 6b0cdc5..63afa11 100644 --- a/src/errors/injectable.rs +++ b/src/errors/injectable.rs @@ -1,8 +1,11 @@ +//! Error types for structs implementing Injectable. + use core::fmt; use std::fmt::{Display, Formatter}; use error_stack::Context; +/// Error for when a injectable struct fails to be resolved. #[derive(Debug)] pub struct ResolveError; diff --git a/src/errors/mod.rs b/src/errors/mod.rs index b0d50f0..5f628d6 100644 --- a/src/errors/mod.rs +++ b/src/errors/mod.rs @@ -1,2 +1,4 @@ +//! Error types for various components of the library. + pub mod di_container; pub mod injectable; diff --git a/src/interfaces/any_factory.rs b/src/interfaces/any_factory.rs index 41063e1..98ec144 100644 --- a/src/interfaces/any_factory.rs +++ b/src/interfaces/any_factory.rs @@ -1,3 +1,6 @@ +//! Interface for any factory to ever exist. + use crate::libs::intertrait::CastFrom; +/// Interface for any factory to ever exist. pub trait AnyFactory: CastFrom {} diff --git a/src/interfaces/factory.rs b/src/interfaces/factory.rs index 6f8e7c7..d3d55da 100644 --- a/src/interfaces/factory.rs +++ b/src/interfaces/factory.rs @@ -1,7 +1,18 @@ #![allow(clippy::module_name_repetitions)] + +//! Interface for a factory. + use crate::libs::intertrait::CastFrom; use crate::ptr::TransientPtr; +/// Interface for a factory. +/// +/// # Examples +/// ``` +/// use syrette::interface::factory::IFactory; +/// +/// type StringFactory = dyn IFactory<(), String>; +/// ``` pub trait IFactory<Args, ReturnInterface>: Fn<Args, Output = TransientPtr<ReturnInterface>> + CastFrom where diff --git a/src/interfaces/injectable.rs b/src/interfaces/injectable.rs index 0af1217..31cd21b 100644 --- a/src/interfaces/injectable.rs +++ b/src/interfaces/injectable.rs @@ -1,8 +1,10 @@ +//! Interface for structs that can be injected into or be injected to. use crate::errors::injectable::ResolveError; use crate::libs::intertrait::CastFrom; use crate::ptr::TransientPtr; use crate::DIContainer; +/// Interface for structs that can be injected into or be injected to. pub trait Injectable: CastFrom { /// Resolves the dependencies of the injectable. diff --git a/src/interfaces/mod.rs b/src/interfaces/mod.rs index 497521e..eef7190 100644 --- a/src/interfaces/mod.rs +++ b/src/interfaces/mod.rs @@ -1,3 +1,5 @@ +//! Various useful interfaces. + pub mod any_factory; pub mod injectable; @@ -1,6 +1,7 @@ #![cfg_attr(feature = "factory", feature(unboxed_closures, fn_traits))] #![deny(clippy::all)] #![deny(clippy::pedantic)] +#![deny(missing_docs)] //! Syrette //! @@ -1,8 +1,13 @@ #![allow(clippy::module_name_repetitions)] + +//! Smart pointer type aliases. use std::rc::Rc; +/// A smart pointer unique to the holder. pub type TransientPtr<Interface> = Box<Interface>; +/// A smart pointer to a shared resource. pub type SingletonPtr<Interface> = Rc<Interface>; +/// A smart pointer to a factory. pub type FactoryPtr<FactoryInterface> = Rc<FactoryInterface>; |