From 8c66b98bca6ed0a2990903fe8e0ea72def5c7be8 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 21 Aug 2022 14:19:07 +0200 Subject: refactor!: change errors to be more sane BREAKING CHANGE: Major improvements have been made to error types and the error_stack crate is no longer used --- src/di_container.rs | 134 ++++++++++++++++++++-------------------------------- 1 file changed, 50 insertions(+), 84 deletions(-) (limited to 'src/di_container.rs') diff --git a/src/di_container.rs b/src/di_container.rs index 84fb9e0..c698fac 100644 --- a/src/di_container.rs +++ b/src/di_container.rs @@ -50,29 +50,15 @@ use std::any::type_name; use std::marker::PhantomData; -use error_stack::{report, Report, ResultExt}; - #[cfg(feature = "factory")] use crate::castable_factory::CastableFactory; use crate::di_container_binding_map::DIContainerBindingMap; use crate::errors::di_container::{BindingBuilderError, DIContainerError}; use crate::interfaces::injectable::Injectable; -use crate::libs::intertrait::cast::error::CastError; use crate::libs::intertrait::cast::{CastBox, CastRc}; use crate::provider::{Providable, SingletonProvider, TransientTypeProvider}; use crate::ptr::{SingletonPtr, TransientPtr}; -fn unable_to_cast_binding(err: Report) -> Report -where - Interface: 'static + ?Sized, -{ - err.change_context(DIContainerError) - .attach_printable(format!( - "Unable to cast binding for interface '{}'", - type_name::() - )) -} - /// Binding builder for type `Interface` inside a [`DIContainer`]. pub struct BindingBuilder<'di_container_lt, Interface> where @@ -100,7 +86,7 @@ where /// # Errors /// Will return Err if the associated [`DIContainer`] already have a binding for /// the interface. - pub fn to(&mut self) -> error_stack::Result<(), BindingBuilderError> + pub fn to(&mut self) -> Result<(), BindingBuilderError> where Implementation: Injectable, { @@ -108,10 +94,7 @@ where .bindings .set::(Box::new(TransientTypeProvider::::new())) .ok_or_else(|| { - report!(BindingBuilderError).attach_printable(format!( - "Binding already exists for interface '{}'", - type_name::() - )) + BindingBuilderError::BindingAlreadyExists(type_name::()) })?; Ok(()) @@ -123,25 +106,20 @@ where /// # Errors /// Will return Err if creating the singleton fails or if the /// associated [`DIContainer`] already have a binding for the interface. - pub fn to_singleton( - &mut self, - ) -> error_stack::Result<(), BindingBuilderError> + pub fn to_singleton(&mut self) -> Result<(), BindingBuilderError> where Implementation: Injectable, { let singleton: SingletonPtr = SingletonPtr::from( Implementation::resolve(self.di_container, Vec::new()) - .change_context(BindingBuilderError)?, + .map_err(BindingBuilderError::SingletonResolveFailed)?, ); self.di_container .bindings .set::(Box::new(SingletonProvider::new(singleton))) .ok_or_else(|| { - report!(BindingBuilderError).attach_printable(format!( - "Binding already exists for interface '{}'", - type_name::() - )) + BindingBuilderError::BindingAlreadyExists(type_name::()) })?; Ok(()) @@ -159,7 +137,7 @@ where pub fn to_factory( &mut self, factory_func: &'static dyn Fn>, - ) -> error_stack::Result<(), BindingBuilderError> + ) -> Result<(), BindingBuilderError> where Args: 'static, Return: 'static + ?Sized, @@ -173,10 +151,7 @@ where crate::ptr::FactoryPtr::new(factory_impl), ))) .ok_or_else(|| { - report!(BindingBuilderError).attach_printable(format!( - "Binding already exists for interface '{}'", - type_name::() - )) + BindingBuilderError::BindingAlreadyExists(type_name::()) })?; Ok(()) @@ -194,7 +169,7 @@ where pub fn to_default_factory( &mut self, factory_func: &'static dyn Fn<(), Output = TransientPtr>, - ) -> error_stack::Result<(), BindingBuilderError> + ) -> Result<(), BindingBuilderError> where Return: 'static + ?Sized, { @@ -206,10 +181,7 @@ where crate::ptr::FactoryPtr::new(factory_impl), ))) .ok_or_else(|| { - report!(BindingBuilderError).attach_printable(format!( - "Binding already exists for interface '{}'", - type_name::() - )) + BindingBuilderError::BindingAlreadyExists(type_name::()) })?; Ok(()) @@ -249,9 +221,7 @@ impl DIContainer /// - Resolving the binding for `Interface` fails /// - Casting the binding for `Interface` fails /// - The binding for `Interface` is not transient - pub fn get( - &self, - ) -> error_stack::Result, DIContainerError> + pub fn get(&self) -> Result, DIContainerError> where Interface: 'static + ?Sized, { @@ -268,7 +238,7 @@ impl DIContainer /// - The binding for `Interface` is not a singleton pub fn get_singleton( &self, - ) -> error_stack::Result, DIContainerError> + ) -> Result, DIContainerError> where Interface: 'static + ?Sized, { @@ -288,7 +258,7 @@ impl DIContainer #[cfg(feature = "factory")] pub fn get_factory( &self, - ) -> error_stack::Result, DIContainerError> + ) -> Result, DIContainerError> where Interface: 'static + ?Sized, { @@ -297,20 +267,21 @@ impl DIContainer if let Providable::Factory(binding_factory) = binding_providable { return binding_factory .cast::() - .map_err(unable_to_cast_binding::); + .map_err(|_| DIContainerError::CastFailed(type_name::())); } - Err(report!(DIContainerError).attach_printable(format!( - "Binding for interface '{}' is not a factory", - type_name::() - ))) + Err(DIContainerError::WrongBindingType { + interface: type_name::(), + expected: "factory", + found: binding_providable.to_string().to_lowercase(), + }) } #[doc(hidden)] pub fn get_with_history( &self, dependency_history: Vec<&'static str>, - ) -> error_stack::Result, DIContainerError> + ) -> Result, DIContainerError> where Interface: 'static + ?Sized, { @@ -320,7 +291,7 @@ impl DIContainer if let Providable::Transient(binding_transient) = binding_providable { return binding_transient .cast::() - .map_err(unable_to_cast_binding::); + .map_err(|_| DIContainerError::CastFailed(type_name::())); } #[cfg(feature = "factory")] @@ -329,22 +300,23 @@ impl DIContainer let factory = binding_factory .cast::>() - .map_err(unable_to_cast_binding::)?; + .map_err(|_| DIContainerError::CastFailed(type_name::()))?; return Ok(factory()); } - Err(report!(DIContainerError).attach_printable(format!( - "Binding for interface '{}' is not transient", - type_name::() - ))) + Err(DIContainerError::WrongBindingType { + interface: type_name::(), + expected: "transient", + found: binding_providable.to_string().to_lowercase(), + }) } #[doc(hidden)] pub fn get_singleton_with_history( &self, dependency_history: Vec<&'static str>, - ) -> error_stack::Result, DIContainerError> + ) -> Result, DIContainerError> where Interface: 'static + ?Sized, { @@ -354,30 +326,30 @@ impl DIContainer if let Providable::Singleton(binding_singleton) = binding_providable { return binding_singleton .cast::() - .map_err(unable_to_cast_binding::); + .map_err(|_| DIContainerError::CastFailed(type_name::())); } - Err(report!(DIContainerError).attach_printable(format!( - "Binding for interface '{}' is not a singleton", - type_name::() - ))) + Err(DIContainerError::WrongBindingType { + interface: type_name::(), + expected: "singleton", + found: binding_providable.to_string().to_lowercase(), + }) } fn get_binding_providable( &self, dependency_history: Vec<&'static str>, - ) -> error_stack::Result + ) -> Result where Interface: 'static + ?Sized, { self.bindings .get::()? .provide(self, dependency_history) - .change_context(DIContainerError) - .attach_printable(format!( - "Failed to resolve binding for interface '{}'", - type_name::() - )) + .map_err(|err| DIContainerError::BindingResolveFailed { + reason: err, + interface: type_name::(), + }) } } @@ -395,7 +367,7 @@ mod tests use mockall::mock; use super::*; - use crate::errors::injectable::ResolveError; + use crate::errors::injectable::InjectableError; use crate::provider::IProvider; use crate::ptr::TransientPtr; @@ -450,10 +422,7 @@ mod tests fn resolve( _di_container: &DIContainer, _dependency_history: Vec<&'static str>, - ) -> error_stack::Result< - TransientPtr, - crate::errors::injectable::ResolveError, - > + ) -> Result, crate::errors::injectable::InjectableError> where Self: Sized, { @@ -517,10 +486,7 @@ mod tests fn resolve( _di_container: &DIContainer, _dependency_history: Vec<&'static str>, - ) -> error_stack::Result< - TransientPtr, - crate::errors::injectable::ResolveError, - > + ) -> Result, crate::errors::injectable::InjectableError> where Self: Sized, { @@ -530,7 +496,7 @@ mod tests } #[test] - fn can_bind_to() -> error_stack::Result<(), BindingBuilderError> + fn can_bind_to() -> Result<(), BindingBuilderError> { let mut di_container: DIContainer = DIContainer::new(); @@ -546,7 +512,7 @@ mod tests } #[test] - fn can_bind_to_singleton() -> error_stack::Result<(), BindingBuilderError> + fn can_bind_to_singleton() -> Result<(), BindingBuilderError> { let mut di_container: DIContainer = DIContainer::new(); @@ -563,7 +529,7 @@ mod tests #[test] #[cfg(feature = "factory")] - fn can_bind_to_factory() -> error_stack::Result<(), BindingBuilderError> + fn can_bind_to_factory() -> Result<(), BindingBuilderError> { type IUserManagerFactory = dyn crate::interfaces::factory::IFactory<(), dyn subjects::IUserManager>; @@ -585,7 +551,7 @@ mod tests } #[test] - fn can_get() -> error_stack::Result<(), DIContainerError> + fn can_get() -> Result<(), DIContainerError> { mock! { Provider {} @@ -596,7 +562,7 @@ mod tests &self, di_container: &DIContainer, dependency_history: Vec<&'static str>, - ) -> error_stack::Result; + ) -> Result; } } @@ -620,7 +586,7 @@ mod tests } #[test] - fn can_get_singleton() -> error_stack::Result<(), DIContainerError> + fn can_get_singleton() -> Result<(), DIContainerError> { mock! { Provider {} @@ -631,7 +597,7 @@ mod tests &self, di_container: &DIContainer, dependency_history: Vec<&'static str>, - ) -> error_stack::Result; + ) -> Result; } } @@ -664,7 +630,7 @@ mod tests #[test] #[cfg(feature = "factory")] - fn can_get_factory() -> error_stack::Result<(), DIContainerError> + fn can_get_factory() -> Result<(), DIContainerError> { trait IUserManager { @@ -717,7 +683,7 @@ mod tests &self, di_container: &DIContainer, dependency_history: Vec<&'static str>, - ) -> error_stack::Result; + ) -> Result; } } -- cgit v1.2.3-18-g5258