1use std::{error::Error as StdError, fmt};
7
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
12pub enum ErrorSeverity {
13 Info = 0,
15 Warning = 1,
17 Error = 2,
19 Critical = 3,
21}
22
23impl fmt::Display for ErrorSeverity {
24 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
25 match self {
26 ErrorSeverity::Info => write!(f, "Info"),
27 ErrorSeverity::Warning => write!(f, "Warning"),
28 ErrorSeverity::Error => write!(f, "Error"),
29 ErrorSeverity::Critical => write!(f, "Critical"),
30 }
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36pub enum ErrorKind {
37 IPC,
39 FileSystem,
41 Configuration,
43 Service,
45 Provider,
47 Other,
49}
50
51impl fmt::Display for ErrorKind {
52 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
53 match self {
54 ErrorKind::IPC => write!(f, "IPC"),
55 ErrorKind::FileSystem => write!(f, "FileSystem"),
56 ErrorKind::Configuration => write!(f, "Configuration"),
57 ErrorKind::Service => write!(f, "Service"),
58 ErrorKind::Provider => write!(f, "Provider"),
59 ErrorKind::Other => write!(f, "Other"),
60 }
61 }
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct ErrorContext {
67 pub message:String,
69 pub kind:ErrorKind,
71 pub severity:ErrorSeverity,
73 pub operation:Option<String>,
75 pub component:Option<String>,
77}
78
79impl ErrorContext {
80 pub fn new(message:impl Into<String>) -> Self {
82 Self {
83 message:message.into(),
84 kind:ErrorKind::Other,
85 severity:ErrorSeverity::Error,
86 operation:None,
87 component:None,
88 }
89 }
90
91 pub fn with_kind(mut self, kind:ErrorKind) -> Self {
93 self.kind = kind;
94 self
95 }
96
97 pub fn with_severity(mut self, severity:ErrorSeverity) -> Self {
99 self.severity = severity;
100 self
101 }
102
103 pub fn with_operation(mut self, operation:impl Into<String>) -> Self {
105 self.operation = Some(operation.into());
106 self
107 }
108
109 pub fn with_component(mut self, component:impl Into<String>) -> Self {
111 self.component = Some(component.into());
112 self
113 }
114}
115
116impl fmt::Display for ErrorContext {
117 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "[{}][{}] {}", self.kind, self.severity, self.message)
119 }
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct MountainError {
125 pub context:ErrorContext,
127 pub source:Option<String>,
129 pub stack_trace:Option<String>,
131}
132
133impl MountainError {
134 pub fn new(context:ErrorContext) -> Self { Self { context, source:None, stack_trace:None } }
136
137 pub fn with_source(mut self, source:impl Into<String>) -> Self {
139 self.source = Some(source.into());
140 self
141 }
142
143 pub fn with_stack_trace(mut self, stack_trace:impl Into<String>) -> Self {
145 self.stack_trace = Some(stack_trace.into());
146 self
147 }
148
149 pub fn message(&self) -> &str { &self.context.message }
151
152 pub fn kind(&self) -> ErrorKind { self.context.kind }
154
155 pub fn severity(&self) -> ErrorSeverity { self.context.severity }
157
158 pub fn is_critical(&self) -> bool { self.context.severity == ErrorSeverity::Critical }
160}
161
162impl fmt::Display for MountainError {
163 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
164 write!(f, "{}", self.context)?;
165 if let Some(source) = &self.source {
166 write!(f, " ({})", source)?;
167 }
168 Ok(())
169 }
170}
171
172impl StdError for MountainError {}
173
174impl From<ErrorContext> for MountainError {
175 fn from(context:ErrorContext) -> Self { Self::new(context) }
176}
177
178pub type Result<T> = std::result::Result<T, MountainError>;