dbrest_core/config/
error.rs1use std::fmt;
4use std::num::ParseIntError;
5
6#[derive(Debug)]
8pub enum ConfigError {
9 Io(std::io::Error),
11
12 Parse {
14 line: Option<usize>,
15 message: String,
16 },
17
18 InvalidValue {
20 key: String,
21 value: String,
22 expected: Option<String>,
23 },
24
25 InvalidBool(String),
27
28 InvalidInt { key: String, error: ParseIntError },
30
31 InvalidJsPath(String),
33
34 Base64(base64::DecodeError),
36
37 Utf8(std::string::FromUtf8Error),
39
40 Validation(String),
42}
43
44impl fmt::Display for ConfigError {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 match self {
47 ConfigError::Io(err) => write!(f, "Config file I/O error: {}", err),
48 ConfigError::Parse { line, message } => {
49 if let Some(line_num) = line {
50 write!(f, "Config parse error at line {}: {}", line_num, message)
51 } else {
52 write!(f, "Config parse error: {}", message)
53 }
54 }
55 ConfigError::InvalidValue {
56 key,
57 value,
58 expected,
59 } => {
60 if let Some(exp) = expected {
61 write!(
62 f,
63 "Invalid value '{}' for config key '{}', expected: {}",
64 value, key, exp
65 )
66 } else {
67 write!(f, "Invalid value '{}' for config key '{}'", value, key)
68 }
69 }
70 ConfigError::InvalidBool(value) => {
71 write!(
72 f,
73 "Invalid boolean value '{}', expected: true/false/yes/no/on/off/1/0",
74 value
75 )
76 }
77 ConfigError::InvalidInt { key, error } => {
78 write!(f, "Invalid integer for '{}': {}", key, error)
79 }
80 ConfigError::InvalidJsPath(msg) => {
81 write!(f, "Invalid JWT role claim path: {}", msg)
82 }
83 ConfigError::Base64(err) => write!(f, "Base64 decode error: {}", err),
84 ConfigError::Utf8(err) => write!(f, "UTF-8 decode error: {}", err),
85 ConfigError::Validation(msg) => write!(f, "Config validation error: {}", msg),
86 }
87 }
88}
89
90impl std::error::Error for ConfigError {
91 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
92 match self {
93 ConfigError::Io(err) => Some(err),
94 ConfigError::InvalidInt { error, .. } => Some(error),
95 ConfigError::Base64(err) => Some(err),
96 ConfigError::Utf8(err) => Some(err),
97 _ => None,
98 }
99 }
100}
101
102impl From<std::io::Error> for ConfigError {
103 fn from(err: std::io::Error) -> Self {
104 ConfigError::Io(err)
105 }
106}
107
108impl From<ParseIntError> for ConfigError {
109 fn from(err: ParseIntError) -> Self {
110 ConfigError::InvalidInt {
111 key: "unknown".to_string(),
112 error: err,
113 }
114 }
115}
116
117impl From<base64::DecodeError> for ConfigError {
118 fn from(err: base64::DecodeError) -> Self {
119 ConfigError::Base64(err)
120 }
121}
122
123impl From<std::string::FromUtf8Error> for ConfigError {
124 fn from(err: std::string::FromUtf8Error) -> Self {
125 ConfigError::Utf8(err)
126 }
127}
128
129impl From<ConfigError> for crate::error::Error {
131 fn from(err: ConfigError) -> Self {
132 crate::error::Error::InvalidConfig {
133 message: err.to_string(),
134 }
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_config_error_display() {
144 let err = ConfigError::InvalidBool("maybe".to_string());
145 assert!(err.to_string().contains("maybe"));
146
147 let err = ConfigError::Validation("test error".to_string());
148 assert!(err.to_string().contains("test error"));
149 }
150
151 #[test]
152 fn test_config_error_parse_with_line() {
153 let err = ConfigError::Parse {
154 line: Some(42),
155 message: "unexpected token".to_string(),
156 };
157 let msg = err.to_string();
158 assert!(msg.contains("42"));
159 assert!(msg.contains("unexpected token"));
160 }
161}