qubit_config/
config_error.rs1use thiserror::Error;
18
19use qubit_common::DataType;
20use qubit_value::ValueError;
21
22#[derive(Debug, Error)]
38pub enum ConfigError {
39 #[error("Property not found: {0}")]
41 PropertyNotFound(String),
42
43 #[error("Property '{0}' has no value")]
45 PropertyHasNoValue(String),
46
47 #[error("Type mismatch at '{key}': expected {expected}, actual {actual}")]
49 TypeMismatch {
50 key: String,
52 expected: DataType,
54 actual: DataType,
56 },
57
58 #[error("Type conversion failed at '{key}': {message}")]
60 ConversionError {
61 key: String,
63 message: String,
65 },
66
67 #[error("Index out of bounds: index {index}, length {len}")]
69 IndexOutOfBounds {
70 index: usize,
72 len: usize,
74 },
75
76 #[error("Variable substitution failed: {0}")]
78 SubstitutionError(String),
79
80 #[error("Variable substitution depth exceeded maximum limit: {0}")]
82 SubstitutionDepthExceeded(usize),
83
84 #[error("Configuration merge failed: {0}")]
86 MergeError(String),
87
88 #[error("Property '{0}' is final and cannot be overridden")]
90 PropertyIsFinal(String),
91
92 #[error("IO error: {0}")]
94 IoError(#[from] std::io::Error),
95
96 #[error("Parse error: {0}")]
98 ParseError(String),
99
100 #[error("Deserialization error at '{path}': {message}")]
102 DeserializeError {
103 path: String,
105 message: String,
107 },
108
109 #[error("Configuration error: {0}")]
111 Other(String),
112}
113
114impl ConfigError {
115 #[inline]
127 pub(crate) fn type_mismatch_no_key(expected: DataType, actual: DataType) -> Self {
128 ConfigError::TypeMismatch {
129 key: String::new(),
130 expected,
131 actual,
132 }
133 }
134
135 #[inline]
145 pub(crate) fn conversion_error_no_key(message: impl Into<String>) -> Self {
146 ConfigError::ConversionError {
147 key: String::new(),
148 message: message.into(),
149 }
150 }
151}
152
153impl From<ValueError> for ConfigError {
154 fn from(err: ValueError) -> Self {
155 match err {
156 ValueError::NoValue => ConfigError::PropertyHasNoValue(String::new()),
157 ValueError::TypeMismatch { expected, actual } => {
158 ConfigError::type_mismatch_no_key(expected, actual)
159 }
160 ValueError::ConversionFailed { from, to } => {
161 ConfigError::conversion_error_no_key(format!("From {from} to {to}"))
162 }
163 ValueError::ConversionError(msg) => ConfigError::conversion_error_no_key(msg),
164 ValueError::IndexOutOfBounds { index, len } => {
165 ConfigError::IndexOutOfBounds { index, len }
166 }
167 ValueError::JsonSerializationError(msg) => {
168 ConfigError::conversion_error_no_key(format!("JSON serialization error: {msg}"))
169 }
170 ValueError::JsonDeserializationError(msg) => {
171 ConfigError::conversion_error_no_key(format!("JSON deserialization error: {msg}"))
172 }
173 }
174 }
175}
176
177impl From<(&str, ValueError)> for ConfigError {
178 fn from((key, err): (&str, ValueError)) -> Self {
179 match err {
180 ValueError::NoValue => ConfigError::PropertyHasNoValue(key.to_string()),
181 ValueError::TypeMismatch { expected, actual } => ConfigError::TypeMismatch {
182 key: key.to_string(),
183 expected,
184 actual,
185 },
186 ValueError::ConversionFailed { from, to } => ConfigError::ConversionError {
187 key: key.to_string(),
188 message: format!("From {from} to {to}"),
189 },
190 ValueError::ConversionError(message) => ConfigError::ConversionError {
191 key: key.to_string(),
192 message,
193 },
194 ValueError::IndexOutOfBounds { index, len } => {
195 ConfigError::IndexOutOfBounds { index, len }
196 }
197 ValueError::JsonSerializationError(message) => ConfigError::ConversionError {
198 key: key.to_string(),
199 message: format!("JSON serialization error: {message}"),
200 },
201 ValueError::JsonDeserializationError(message) => ConfigError::ConversionError {
202 key: key.to_string(),
203 message: format!("JSON deserialization error: {message}"),
204 },
205 }
206 }
207}