qubit_config/
config_error.rs1use thiserror::Error;
16
17use qubit_datatype::DataConversionError;
18use qubit_datatype::DataType;
19use qubit_value::ValueError;
20
21#[derive(Debug, Error)]
34pub enum ConfigError {
35 #[error("Property not found: {0}")]
37 PropertyNotFound(String),
38
39 #[error("Property '{0}' has no value")]
41 PropertyHasNoValue(String),
42
43 #[error("Type mismatch at '{key}': expected {expected}, actual {actual}")]
45 TypeMismatch {
46 key: String,
48 expected: DataType,
50 actual: DataType,
52 },
53
54 #[error("Type conversion failed at '{key}': {message}")]
56 ConversionError {
57 key: String,
59 message: String,
61 },
62
63 #[error("Index out of bounds: index {index}, length {len}")]
65 IndexOutOfBounds {
66 index: usize,
68 len: usize,
70 },
71
72 #[error("Variable substitution failed: {0}")]
74 SubstitutionError(String),
75
76 #[error("Variable substitution depth exceeded maximum limit: {0}")]
78 SubstitutionDepthExceeded(usize),
79
80 #[error("Variable substitution cycle detected: {}", chain.join(" -> "))]
82 SubstitutionCycle {
83 chain: Vec<String>,
85 },
86
87 #[error("Configuration merge failed: {0}")]
89 MergeError(String),
90
91 #[error("Property '{0}' is final and cannot be overridden")]
93 PropertyIsFinal(String),
94
95 #[error("Configuration key conflict at '{path}': existing {existing}, incoming {incoming}")]
97 KeyConflict {
98 path: String,
100 existing: String,
102 incoming: String,
104 },
105
106 #[error("IO error: {0}")]
108 IoError(#[from] std::io::Error),
109
110 #[error("Parse error: {0}")]
112 ParseError(String),
113
114 #[error("Deserialization error at '{path}': {message}")]
116 DeserializeError {
117 path: String,
119 message: String,
121 #[source]
123 source: Option<Box<ConfigError>>,
124 },
125
126 #[error("Configuration error: {0}")]
128 Other(String),
129}
130
131impl ConfigError {
132 #[inline]
144 pub(crate) fn type_mismatch_no_key(expected: DataType, actual: DataType) -> Self {
145 ConfigError::TypeMismatch {
146 key: String::new(),
147 expected,
148 actual,
149 }
150 }
151
152 #[inline]
162 pub(crate) fn conversion_error_no_key(message: impl Into<String>) -> Self {
163 ConfigError::ConversionError {
164 key: String::new(),
165 message: message.into(),
166 }
167 }
168
169 pub fn from_data_conversion_error(key: &str, err: DataConversionError) -> Self {
180 match err {
181 DataConversionError::NoValue => ConfigError::PropertyHasNoValue(key.to_string()),
182 DataConversionError::ConversionFailed { from, to } => ConfigError::ConversionError {
183 key: key.to_string(),
184 message: format!("From {from} to {to}"),
185 },
186 DataConversionError::ConversionError(message) => ConfigError::ConversionError {
187 key: key.to_string(),
188 message,
189 },
190 DataConversionError::JsonSerializationError(message) => ConfigError::ConversionError {
191 key: key.to_string(),
192 message: format!("JSON serialization error: {message}"),
193 },
194 DataConversionError::JsonDeserializationError(message) => {
195 ConfigError::ConversionError {
196 key: key.to_string(),
197 message: format!("JSON deserialization error: {message}"),
198 }
199 }
200 }
201 }
202}
203
204impl From<ValueError> for ConfigError {
205 fn from(err: ValueError) -> Self {
206 match err {
207 ValueError::NoValue => ConfigError::PropertyHasNoValue(String::new()),
208 ValueError::TypeMismatch { expected, actual } => {
209 ConfigError::type_mismatch_no_key(expected, actual)
210 }
211 ValueError::ConversionFailed { from, to } => {
212 ConfigError::conversion_error_no_key(format!("From {from} to {to}"))
213 }
214 ValueError::ConversionError(msg) => ConfigError::conversion_error_no_key(msg),
215 ValueError::IndexOutOfBounds { index, len } => {
216 ConfigError::IndexOutOfBounds { index, len }
217 }
218 ValueError::JsonSerializationError(msg) => {
219 ConfigError::conversion_error_no_key(format!("JSON serialization error: {msg}"))
220 }
221 ValueError::JsonDeserializationError(msg) => {
222 ConfigError::conversion_error_no_key(format!("JSON deserialization error: {msg}"))
223 }
224 }
225 }
226}
227
228impl From<(&str, ValueError)> for ConfigError {
229 fn from((key, err): (&str, ValueError)) -> Self {
230 match err {
231 ValueError::NoValue => ConfigError::PropertyHasNoValue(key.to_string()),
232 ValueError::TypeMismatch { expected, actual } => ConfigError::TypeMismatch {
233 key: key.to_string(),
234 expected,
235 actual,
236 },
237 ValueError::ConversionFailed { from, to } => ConfigError::ConversionError {
238 key: key.to_string(),
239 message: format!("From {from} to {to}"),
240 },
241 ValueError::ConversionError(message) => ConfigError::ConversionError {
242 key: key.to_string(),
243 message,
244 },
245 ValueError::IndexOutOfBounds { index, len } => {
246 ConfigError::IndexOutOfBounds { index, len }
247 }
248 ValueError::JsonSerializationError(message) => ConfigError::ConversionError {
249 key: key.to_string(),
250 message: format!("JSON serialization error: {message}"),
251 },
252 ValueError::JsonDeserializationError(message) => ConfigError::ConversionError {
253 key: key.to_string(),
254 message: format!("JSON deserialization error: {message}"),
255 },
256 }
257 }
258}