Mountain/Error/
ConfigurationError.rs

1//! # Configuration Error Types
2//!
3//! Provides configuration management error types for Mountain.
4//! Used for all configuration related errors.
5
6use std::{error::Error as StdError, fmt};
7
8use serde::{Deserialize, Serialize};
9
10use super::CoreError::{ErrorContext, ErrorKind, ErrorSeverity, MountainError, Result};
11
12/// Configuration operation error types
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub enum ConfigurationError {
15	/// Configuration key not found
16	KeyNotFound { context:ErrorContext, key:String, section:Option<String> },
17	/// Invalid configuration value
18	InvalidValue { context:ErrorContext, key:String, expected_type:String },
19	/// Configuration validation failed
20	ValidationFailed { context:ErrorContext, errors:Vec<String> },
21	/// Configuration parse error
22	ParseError { context:ErrorContext, format:String, source:String },
23	/// Configuration file not found
24	FileNotFound { context:ErrorContext, path:String },
25	/// Configuration file read error
26	FileReadError { context:ErrorContext, path:String, source:String },
27	/// Configuration file write error
28	FileWriteError { context:ErrorContext, path:String, source:String },
29	/// Circular dependency detected
30	CircularDependency { context:ErrorContext, keys:Vec<String> },
31}
32
33impl ConfigurationError {
34	/// Get the error context
35	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	/// Create a key not found error
49	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) = &section {
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	/// Create an invalid value error
66	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	/// Create a validation failed error
82	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	/// Create a parse error
92	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	/// Create a file not found error
103	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	/// Create a circular dependency error
114	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}