Skip to main content

sword_core/injectables/
error.rs

1use std::fmt::{self, Display, Formatter};
2
3#[derive(Debug)]
4pub enum DependencyInjectionError {
5    BuildFailed {
6        type_name: String,
7        source: Box<DependencyInjectionError>,
8    },
9
10    DependencyNotFound {
11        type_name: String,
12    },
13
14    CircularDependency,
15}
16
17impl DependencyInjectionError {
18    pub fn build_failed(type_name: impl Into<String>, source: DependencyInjectionError) -> Self {
19        Self::BuildFailed {
20            type_name: type_name.into(),
21            source: Box::new(source),
22        }
23    }
24
25    pub fn dependency_not_found(type_name: impl Into<String>) -> Self {
26        Self::DependencyNotFound {
27            type_name: type_name.into(),
28        }
29    }
30
31    pub fn diagnostic_context(&self) -> Vec<(String, String)> {
32        let mut context = Vec::new();
33        self.collect_diagnostic_context(&mut context);
34        context
35    }
36
37    pub fn dependency_path(&self) -> Option<&str> {
38        match self {
39            Self::BuildFailed { type_name, .. } => Some(type_name.as_str()),
40            Self::DependencyNotFound { .. } | Self::CircularDependency => None,
41        }
42    }
43
44    pub fn missing_dependency_path(&self) -> Option<&str> {
45        match self {
46            Self::BuildFailed { source, .. } => source.missing_dependency_path(),
47            Self::DependencyNotFound { type_name } => Some(type_name.as_str()),
48            Self::CircularDependency => None,
49        }
50    }
51
52    fn collect_diagnostic_context(&self, context: &mut Vec<(String, String)>) {
53        match self {
54            Self::BuildFailed { type_name, source } => {
55                context.push(("dependency_path".to_string(), type_name.clone()));
56                source.collect_diagnostic_context(context);
57            }
58            Self::DependencyNotFound { type_name } => {
59                context.push(("missing_dependency_path".to_string(), type_name.clone()));
60            }
61            Self::CircularDependency => {}
62        }
63    }
64}
65
66impl Display for DependencyInjectionError {
67    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
68        match self {
69            Self::BuildFailed { type_name, source } => write!(
70                f,
71                "Failed to build dependency '{}': {}",
72                short_type_name(type_name),
73                source
74            ),
75            Self::DependencyNotFound { type_name } => write!(
76                f,
77                "Dependency '{}' not found in dependency container",
78                short_type_name(type_name)
79            ),
80            Self::CircularDependency => {
81                write!(f, "Circular dependency detected in dependency container")
82            }
83        }
84    }
85}
86
87impl std::error::Error for DependencyInjectionError {
88    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
89        match self {
90            Self::BuildFailed { source, .. } => Some(source.as_ref()),
91            Self::DependencyNotFound { .. } | Self::CircularDependency => None,
92        }
93    }
94}
95
96fn short_type_name(type_name: &str) -> &str {
97    type_name.rsplit("::").next().unwrap_or(type_name)
98}