1use std::{error::Error as StdError, fmt};
19
20use serde::{Deserialize, Serialize};
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
25pub enum ErrorSeverity {
26 Info = 0,
28
29 Warning = 1,
31
32 Error = 2,
34
35 Critical = 3,
37}
38
39impl fmt::Display for ErrorSeverity {
40 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 ErrorSeverity::Info => write!(f, "Info"),
43
44 ErrorSeverity::Warning => write!(f, "Warning"),
45
46 ErrorSeverity::Error => write!(f, "Error"),
47
48 ErrorSeverity::Critical => write!(f, "Critical"),
49 }
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
56pub enum ErrorKind {
57 IPC,
59
60 FileSystem,
62
63 Configuration,
65
66 Service,
68
69 Provider,
71
72 Other,
74}
75
76impl fmt::Display for ErrorKind {
77 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
78 match self {
79 ErrorKind::IPC => write!(f, "IPC"),
80
81 ErrorKind::FileSystem => write!(f, "FileSystem"),
82
83 ErrorKind::Configuration => write!(f, "Configuration"),
84
85 ErrorKind::Service => write!(f, "Service"),
86
87 ErrorKind::Provider => write!(f, "Provider"),
88
89 ErrorKind::Other => write!(f, "Other"),
90 }
91 }
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ErrorContext {
100 pub message:String,
102
103 pub kind:ErrorKind,
105
106 pub severity:ErrorSeverity,
108
109 pub operation:Option<String>,
111
112 pub component:Option<String>,
114}
115
116impl ErrorContext {
117 pub fn new(message:impl Into<String>) -> Self {
119 Self {
120 message:message.into(),
121
122 kind:ErrorKind::Other,
123
124 severity:ErrorSeverity::Error,
125
126 operation:None,
127
128 component:None,
129 }
130 }
131
132 pub fn with_kind(mut self, kind:ErrorKind) -> Self {
133 self.kind = kind;
134
135 self
136 }
137
138 pub fn with_severity(mut self, severity:ErrorSeverity) -> Self {
139 self.severity = severity;
140
141 self
142 }
143
144 pub fn with_operation(mut self, operation:impl Into<String>) -> Self {
145 self.operation = Some(operation.into());
146
147 self
148 }
149
150 pub fn with_component(mut self, component:impl Into<String>) -> Self {
151 self.component = Some(component.into());
152
153 self
154 }
155}
156
157impl fmt::Display for ErrorContext {
158 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
159 write!(f, "[{}][{}] {}", self.kind, self.severity, self.message)
160 }
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct MountainError {
167 pub context:ErrorContext,
169
170 pub source:Option<String>,
172
173 pub stack_trace:Option<String>,
175}
176
177impl MountainError {
178 pub fn new(context:ErrorContext) -> Self { Self { context, source:None, stack_trace:None } }
180
181 pub fn with_source(mut self, source:impl Into<String>) -> Self {
184 self.source = Some(source.into());
185
186 self
187 }
188
189 pub fn with_stack_trace(mut self, stack_trace:impl Into<String>) -> Self {
191 self.stack_trace = Some(stack_trace.into());
192
193 self
194 }
195
196 pub fn message(&self) -> &str { &self.context.message }
198
199 pub fn kind(&self) -> ErrorKind { self.context.kind }
201
202 pub fn severity(&self) -> ErrorSeverity { self.context.severity }
204
205 pub fn is_critical(&self) -> bool { self.context.severity == ErrorSeverity::Critical }
207}
208
209impl fmt::Display for MountainError {
210 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
211 write!(f, "{}", self.context)?;
212
213 if let Some(source) = &self.source {
214 write!(f, " ({})", source)?;
215 }
216
217 Ok(())
218 }
219}
220
221impl StdError for MountainError {}
222
223impl From<ErrorContext> for MountainError {
224 fn from(context:ErrorContext) -> Self { Self::new(context) }
225}
226
227pub type Result<T> = std::result::Result<T, MountainError>;