better_config_core/
error.rs1use std::{error::Error as StdError, fmt};
2
3#[derive(Debug)]
4pub enum Error {
5 LoadFileError {
7 name: String,
8 source: Option<Box<dyn StdError + Send + Sync>>,
9 },
10 ParseError {
12 name: String,
13 format: String,
14 source: Option<Box<dyn StdError + Send + Sync>>,
15 },
16 ValueError {
18 key: String,
19 expected_type: String,
20 actual_value: String,
21 },
22 InvalidPathError { path: String, reason: String },
24 ValidationError { message: String },
26 IoError {
28 operation: String,
29 source: Option<Box<dyn StdError + Send + Sync>>,
30 },
31}
32
33impl fmt::Display for Error {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 match self {
36 Error::LoadFileError { name, source } => {
37 write!(f, "Failed to load file {}", name)?;
38 if let Some(source) = source {
39 write!(f, ": {}", source)?;
40 }
41 Ok(())
42 }
43 Error::ParseError {
44 name,
45 format,
46 source,
47 } => {
48 write!(f, "Failed to parse {} file {} as {}", format, name, format)?;
49 if let Some(source) = source {
50 write!(f, ": {}", source)?;
51 }
52 Ok(())
53 }
54 Error::ValueError {
55 key,
56 expected_type,
57 actual_value,
58 } => {
59 write!(
60 f,
61 "Invalid value for key '{}': expected {}, got '{}'",
62 key, expected_type, actual_value
63 )
64 }
65 Error::InvalidPathError { path, reason } => {
66 write!(f, "Invalid path '{}': {}", path, reason)
67 }
68 Error::ValidationError { message } => {
69 write!(f, "Configuration validation failed: {}", message)
70 }
71 Error::IoError { operation, source } => {
72 write!(f, "I/O operation '{}' failed", operation)?;
73 if let Some(source) = source {
74 write!(f, ": {}", source)?;
75 }
76 Ok(())
77 }
78 }
79 }
80}
81
82impl StdError for Error {
83 fn source(&self) -> Option<&(dyn StdError + 'static)> {
84 match self {
85 Error::LoadFileError { source, .. } => {
86 source.as_deref().map(|e| e as &(dyn StdError + 'static))
87 }
88 Error::ParseError { source, .. } => {
89 source.as_deref().map(|e| e as &(dyn StdError + 'static))
90 }
91 Error::IoError { source, .. } => {
92 source.as_deref().map(|e| e as &(dyn StdError + 'static))
93 }
94 _ => None,
95 }
96 }
97}
98
99impl Error {
101 pub fn file_not_found(path: &str) -> Self {
102 Error::LoadFileError {
103 name: path.to_string(),
104 source: Some(Box::new(std::io::Error::new(
105 std::io::ErrorKind::NotFound,
106 format!("File '{}' not found", path),
107 ))),
108 }
109 }
110
111 pub fn parse_json_error(path: &str, source: impl StdError + Send + Sync + 'static) -> Self {
112 Error::ParseError {
113 name: path.to_string(),
114 format: "JSON".to_string(),
115 source: Some(Box::new(source)),
116 }
117 }
118
119 pub fn parse_yaml_error(path: &str, source: impl StdError + Send + Sync + 'static) -> Self {
120 Error::ParseError {
121 name: path.to_string(),
122 format: "YAML".to_string(),
123 source: Some(Box::new(source)),
124 }
125 }
126
127 pub fn parse_toml_error(path: &str, source: impl StdError + Send + Sync + 'static) -> Self {
128 Error::ParseError {
129 name: path.to_string(),
130 format: "TOML".to_string(),
131 source: Some(Box::new(source)),
132 }
133 }
134
135 pub fn invalid_path(path: &str, reason: &str) -> Self {
136 Error::InvalidPathError {
137 path: path.to_string(),
138 reason: reason.to_string(),
139 }
140 }
141
142 pub fn value_conversion_error(key: &str, expected: &str, actual: &str) -> Self {
143 Error::ValueError {
144 key: key.to_string(),
145 expected_type: expected.to_string(),
146 actual_value: actual.to_string(),
147 }
148 }
149}