ferrous_di/error.rs
1//! Error types for the dependency injection container.
2
3use std::fmt;
4
5/// Dependency injection errors
6///
7/// Represents the various error conditions that can occur during service
8/// registration, resolution, or container operations in ferrous-di.
9///
10/// # Examples
11///
12/// ```rust
13/// use ferrous_di::{DiError, ServiceCollection, Resolver};
14///
15/// // Example of NotFound error
16/// let provider = ServiceCollection::new().build();
17/// match provider.get::<String>() {
18/// Err(DiError::NotFound(type_name)) => {
19/// assert_eq!(type_name, "alloc::string::String");
20/// println!("Service not found: {}", type_name);
21/// }
22/// _ => unreachable!(),
23/// }
24/// ```
25///
26/// ```rust
27/// use ferrous_di::DiError;
28///
29/// // Examples of error types
30/// let not_found = DiError::NotFound("MyService");
31/// let type_mismatch = DiError::TypeMismatch("std::string::String");
32/// let circular = DiError::Circular(vec!["ServiceA", "ServiceB", "ServiceA"]);
33/// let wrong_lifetime = DiError::WrongLifetime("Cannot resolve scoped from singleton");
34/// let depth_exceeded = DiError::DepthExceeded(100);
35///
36/// // All errors implement Display
37/// println!("Error: {}", not_found);
38/// println!("Error: {}", circular);
39/// ```
40#[derive(Debug, Clone)]
41pub enum DiError {
42 /// Service not registered
43 NotFound(&'static str),
44 /// Type downcast failed
45 TypeMismatch(&'static str),
46 /// Circular dependency detected (includes path)
47 Circular(Vec<&'static str>),
48 /// Invalid lifetime resolution (e.g., scoped from root)
49 WrongLifetime(&'static str),
50 /// Maximum recursion depth exceeded
51 DepthExceeded(usize),
52}
53
54impl fmt::Display for DiError {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 DiError::NotFound(name) => write!(f, "Service not found: {}", name),
58 DiError::TypeMismatch(name) => write!(f, "Type mismatch for: {}", name),
59 DiError::Circular(path) => {
60 write!(f, "Circular dependency: {}", path.join(" -> "))
61 }
62 DiError::WrongLifetime(msg) => write!(f, "Lifetime error: {}", msg),
63 DiError::DepthExceeded(depth) => write!(f, "Max depth {} exceeded", depth),
64 }
65 }
66}
67
68impl std::error::Error for DiError {}
69
70/// Result type for DI operations
71///
72/// A convenience type alias for `Result<T, DiError>` used throughout ferrous-di.
73/// This follows the common Rust pattern of having a crate-specific Result type
74/// to reduce boilerplate in function signatures.
75///
76/// # Examples
77///
78/// ```rust
79/// use ferrous_di::{DiResult, DiError};
80///
81/// fn create_service() -> DiResult<String> {
82/// Ok("service created".to_string())
83/// }
84///
85/// fn failing_operation() -> DiResult<()> {
86/// Err(DiError::NotFound("some_service"))
87/// }
88///
89/// // Usage
90/// match create_service() {
91/// Ok(service) => println!("Success: {}", service),
92/// Err(e) => eprintln!("Error: {}", e),
93/// }
94/// ```
95pub type DiResult<T> = Result<T, DiError>;