sword_core/injectables/
error.rs1use 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}