Mountain/Error/
ConfigurationError.rs1use std::{error::Error as StdError, fmt};
7
8use serde::{Deserialize, Serialize};
9
10use super::CoreError::{ErrorContext, ErrorKind, ErrorSeverity, MountainError, Result};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub enum ConfigurationError {
15 KeyNotFound { context:ErrorContext, key:String, section:Option<String> },
17 InvalidValue { context:ErrorContext, key:String, expected_type:String },
19 ValidationFailed { context:ErrorContext, errors:Vec<String> },
21 ParseError { context:ErrorContext, format:String, source:String },
23 FileNotFound { context:ErrorContext, path:String },
25 FileReadError { context:ErrorContext, path:String, source:String },
27 FileWriteError { context:ErrorContext, path:String, source:String },
29 CircularDependency { context:ErrorContext, keys:Vec<String> },
31}
32
33impl ConfigurationError {
34 pub fn context(&self) -> &ErrorContext {
36 match self {
37 ConfigurationError::KeyNotFound { context, .. } => context,
38 ConfigurationError::InvalidValue { context, .. } => context,
39 ConfigurationError::ValidationFailed { context, .. } => context,
40 ConfigurationError::ParseError { context, .. } => context,
41 ConfigurationError::FileNotFound { context, .. } => context,
42 ConfigurationError::FileReadError { context, .. } => context,
43 ConfigurationError::FileWriteError { context, .. } => context,
44 ConfigurationError::CircularDependency { context, .. } => context,
45 }
46 }
47
48 pub fn key_not_found(key:impl Into<String>, section:Option<String>) -> Self {
50 let key = key.into();
51 let message = if let Some(section) = §ion {
52 format!("Configuration key '{}' not found in section '{}'", key, section)
53 } else {
54 format!("Configuration key '{}' not found", key)
55 };
56 Self::KeyNotFound {
57 context:ErrorContext::new(message)
58 .with_kind(ErrorKind::Configuration)
59 .with_severity(ErrorSeverity::Error),
60 key,
61 section,
62 }
63 }
64
65 pub fn invalid_value(key:impl Into<String>, expected_type:impl Into<String>) -> Self {
67 let key_str = key.into();
68 let expected_type_str = expected_type.into();
69 Self::InvalidValue {
70 context:ErrorContext::new(format!(
71 "Invalid value for key '{}': expected type '{}'",
72 key_str, expected_type_str
73 ))
74 .with_kind(ErrorKind::Configuration)
75 .with_severity(ErrorSeverity::Error),
76 key:key_str,
77 expected_type:expected_type_str,
78 }
79 }
80
81 pub fn validation_failed(errors:Vec<String>) -> Self {
83 Self::ValidationFailed {
84 context:ErrorContext::new(format!("Configuration validation failed with {} error(s)", errors.len()))
85 .with_kind(ErrorKind::Configuration)
86 .with_severity(ErrorSeverity::Error),
87 errors,
88 }
89 }
90
91 pub fn parse_error(format:impl Into<String>, source:impl Into<String>, message:impl Into<String>) -> Self {
93 Self::ParseError {
94 context:ErrorContext::new(message)
95 .with_kind(ErrorKind::Configuration)
96 .with_severity(ErrorSeverity::Error),
97 format:format.into(),
98 source:source.into(),
99 }
100 }
101
102 pub fn file_not_found(path:impl Into<String>) -> Self {
104 let path_str = path.into();
105 Self::FileNotFound {
106 context:ErrorContext::new(format!("Configuration file not found: {}", path_str))
107 .with_kind(ErrorKind::Configuration)
108 .with_severity(ErrorSeverity::Error),
109 path:path_str,
110 }
111 }
112
113 pub fn circular_dependency(keys:Vec<String>) -> Self {
115 Self::CircularDependency {
116 context:ErrorContext::new(format!("Circular dependency detected in configuration: {}", keys.join(" -> ")))
117 .with_kind(ErrorKind::Configuration)
118 .with_severity(ErrorSeverity::Critical),
119 keys,
120 }
121 }
122}
123
124impl fmt::Display for ConfigurationError {
125 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.context()) }
126}
127
128impl StdError for ConfigurationError {}
129
130impl From<ConfigurationError> for MountainError {
131 fn from(err:ConfigurationError) -> Self { MountainError::new(err.context().clone()).with_source(err.to_string()) }
132}