1use std::error::Error;
6use std::fmt;
7
8#[derive(Debug)]
13pub enum BuildError {
14 MissingConfig { module: &'static str },
16
17 MissingRequirements { module: &'static str },
19
20 InvalidConfig {
22 module: &'static str,
23 reason: &'static str,
24 },
25
26 ModuleFailed {
28 module: &'static str,
29 source: Box<dyn Error + Send + Sync>,
30 },
31}
32
33impl fmt::Display for BuildError {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 BuildError::MissingConfig { module } => {
37 write!(f, "missing config for module `{module}`")
38 }
39 BuildError::MissingRequirements { module } => {
40 write!(f, "missing requirements for module `{module}`")
41 }
42 BuildError::InvalidConfig { module, reason } => {
43 write!(f, "invalid config for module `{module}`: {reason}")
44 }
45 BuildError::ModuleFailed { module, source } => {
46 write!(f, "module `{module}` failed: {source}")
47 }
48 }
49 }
50}
51
52impl Error for BuildError {
53 fn source(&self) -> Option<&(dyn Error + 'static)> {
54 match self {
55 BuildError::ModuleFailed { source, .. } => Some(source.as_ref()),
56 _ => None,
57 }
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn missing_config_display() {
67 let error = BuildError::MissingConfig {
68 module: "my_module",
69 };
70 let msg = error.to_string();
71 assert!(msg.contains("my_module"));
72 assert!(msg.contains("missing config"));
73 assert!(error.source().is_none());
74 }
75
76 #[test]
77 fn missing_requirements_display() {
78 let error = BuildError::MissingRequirements {
79 module: "test_module",
80 };
81 let msg = error.to_string();
82 assert!(msg.contains("test_module"));
83 assert!(msg.contains("missing requirements"));
84 assert!(error.source().is_none());
85 }
86
87 #[test]
88 fn invalid_config_display() {
89 let error = BuildError::InvalidConfig {
90 module: "cfg_module",
91 reason: "bad value",
92 };
93 let msg = error.to_string();
94 assert!(msg.contains("cfg_module"));
95 assert!(msg.contains("invalid config"));
96 assert!(msg.contains("bad value"));
97 assert!(error.source().is_none());
98 }
99
100 #[test]
101 fn module_failed_display_and_source() {
102 let inner = std::io::Error::other("inner error");
103 let error = BuildError::ModuleFailed {
104 module: "fail_mod",
105 source: Box::new(inner),
106 };
107 let msg = error.to_string();
108 assert!(msg.contains("fail_mod"));
109 assert!(msg.contains("failed"));
110 assert!(msg.contains("inner error"));
111 assert!(error.source().is_some());
112 }
113}