From ca86952c1486b7f2313fef62e6cacf36e248efd2 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 13 Jul 2024 16:26:28 +0200 Subject: refactor: move & rename all mod.rs files --- src/di_container/blocking.rs | 722 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 722 insertions(+) create mode 100644 src/di_container/blocking.rs (limited to 'src/di_container/blocking.rs') diff --git a/src/di_container/blocking.rs b/src/di_container/blocking.rs new file mode 100644 index 0000000..d8b0d59 --- /dev/null +++ b/src/di_container/blocking.rs @@ -0,0 +1,722 @@ +//! Blocking dependency injection container. +//! +//! # Examples +//! ``` +//! use std::collections::HashMap; +//! use std::error::Error; +//! +//! use syrette::{injectable, DIContainer}; +//! +//! trait IDatabaseService +//! { +//! fn get_all_records(&self, table_name: String) -> HashMap; +//! } +//! +//! struct DatabaseService {} +//! +//! #[injectable(IDatabaseService)] +//! impl DatabaseService +//! { +//! fn new() -> Self +//! { +//! Self {} +//! } +//! } +//! +//! impl IDatabaseService for DatabaseService +//! { +//! fn get_all_records(&self, table_name: String) -> HashMap +//! { +//! // Do stuff here +//! HashMap::::new() +//! } +//! } +//! +//! fn main() -> Result<(), Box> +//! { +//! let mut di_container = DIContainer::new(); +//! +//! di_container +//! .bind::() +//! .to::() +//! .map_err(|err| err.to_string())?; +//! +//! let database_service = di_container +//! .get::() +//! .map_err(|err| err.to_string())? +//! .transient()?; +//! +//! Ok(()) +//! } +//! ``` +use std::any::type_name; + +use crate::di_container::binding_storage::DIContainerBindingStorage; +use crate::di_container::blocking::binding::builder::BindingBuilder; +use crate::di_container::BindingOptions; +use crate::errors::di_container::DIContainerError; +use crate::private::cast::boxed::CastBox; +use crate::private::cast::rc::CastRc; +use crate::provider::blocking::{IProvider, Providable}; +use crate::ptr::SomePtr; +use crate::util::use_double; + +use_double!(crate::dependency_history::DependencyHistory); + +pub mod binding; + +#[cfg(not(test))] +pub(crate) type BindingOptionsWithLt<'a> = BindingOptions<'a>; + +#[cfg(test)] +pub(crate) type BindingOptionsWithLt = BindingOptions<'static>; + +/// Blocking dependency injection container. +#[derive(Default)] +pub struct DIContainer +{ + binding_storage: DIContainerBindingStorage>, +} + +impl DIContainer +{ + /// Returns a new `DIContainer`. + #[must_use] + pub fn new() -> Self + { + Self { + binding_storage: DIContainerBindingStorage::new(), + } + } +} + +#[cfg_attr(test, mockall::automock)] +impl DIContainer +{ + /// Returns a new [`BindingBuilder`] for the given interface. + /// + /// # Examples + /// ``` + /// # use syrette::{DIContainer, injectable}; + /// # + /// # struct DiskWriter {} + /// # + /// # #[injectable] + /// # impl DiskWriter + /// # { + /// # fn new() -> Self + /// # { + /// # Self {} + /// # } + /// # } + /// # + /// # fn main() -> Result<(), Box> { + /// let mut di_container = DIContainer::new(); + /// + /// di_container.bind::().to::()?; + /// # + /// # Ok(()) + /// # } + /// ``` + #[allow(clippy::missing_panics_doc)] + pub fn bind(&mut self) -> BindingBuilder<'_, Interface> + where + Interface: 'static + ?Sized, + { + #[cfg(test)] + panic!("Nope"); + + #[cfg(not(test))] + BindingBuilder::new(self, DependencyHistory::new) + } + + /// Returns the type bound with `Interface`. + /// + /// # Errors + /// Will return `Err` if: + /// - No binding for `Interface` exists + /// - Resolving the binding for `Interface` fails + /// - Casting the binding for `Interface` fails + /// + /// # Examples + /// ``` + /// # use syrette::{DIContainer, injectable}; + /// # + /// # struct DeviceManager {} + /// # + /// # #[injectable] + /// # impl DeviceManager + /// # { + /// # fn new() -> Self + /// # { + /// # Self {} + /// # } + /// # } + /// # + /// # fn main() -> Result<(), Box> { + /// let mut di_container = DIContainer::new(); + /// + /// di_container.bind::().to::()?; + /// + /// let device_manager = di_container.get::()?.transient(); + /// # + /// # Ok(()) + /// # } + /// ``` + pub fn get(&self) -> Result, DIContainerError> + where + Interface: 'static + ?Sized, + { + self.get_bound::(DependencyHistory::new(), BindingOptions::new()) + } + + /// Returns the type bound with `Interface` and the specified name. + /// + /// # Errors + /// Will return `Err` if: + /// - No binding for `Interface` with name `name` exists + /// - Resolving the binding for `Interface` fails + /// - Casting the binding for `Interface` fails + /// + /// # Examples + /// ``` + /// # use syrette::{DIContainer, injectable}; + /// # + /// # struct DeviceManager {} + /// # + /// # #[injectable] + /// # impl DeviceManager + /// # { + /// # fn new() -> Self + /// # { + /// # Self {} + /// # } + /// # } + /// # + /// # fn main() -> Result<(), Box> { + /// let mut di_container = DIContainer::new(); + /// + /// di_container + /// .bind::() + /// .to::()? + /// .in_transient_scope() + /// .when_named("usb")?; + /// + /// let device_manager = di_container.get_named::("usb")?.transient(); + /// # + /// # Ok(()) + /// # } + /// ``` + pub fn get_named( + &self, + name: &'static str, + ) -> Result, DIContainerError> + where + Interface: 'static + ?Sized, + { + self.get_bound::( + DependencyHistory::new(), + BindingOptions::new().name(name), + ) + } + + /// Returns the type bound with `Interface` where the binding has the specified + /// options. + /// + /// `dependency_history` is passed to the bound type when it is being resolved. + /// + /// # Errors + /// Will return `Err` if: + /// - No binding for `Interface` exists + /// - Resolving the binding for `Interface` fails + /// - Casting the binding for `Interface` fails + /// + /// # Examples + /// ```no_run + /// # use syrette::di_container::blocking::DIContainer; + /// # use syrette::dependency_history::DependencyHistory; + /// # use syrette::di_container::BindingOptions; + /// # + /// # struct EventHandler {} + /// # struct Button {} + /// # + /// # fn main() -> Result<(), Box> { + /// # let di_container = DIContainer::new(); + /// # + /// let mut dependency_history = DependencyHistory::new(); + /// + /// dependency_history.push::(); + /// + /// di_container.get_bound::