1use std::{error::Error as StdError, fmt};
21
22use serde::{Deserialize, Serialize};
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
26pub enum ErrorSeverity {
27 Info = 0,
28 Warning = 1,
29 Error = 2,
30 Critical = 3,
31}
32
33impl fmt::Display for ErrorSeverity {
34 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 ErrorSeverity::Info => write!(f, "Info"),
37 ErrorSeverity::Warning => write!(f, "Warning"),
38 ErrorSeverity::Error => write!(f, "Error"),
39 ErrorSeverity::Critical => write!(f, "Critical"),
40 }
41 }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46pub enum ErrorKind {
47 IPC,
48 FileSystem,
49 Configuration,
50 Service,
51 Provider,
52 Other,
53}
54
55impl fmt::Display for ErrorKind {
56 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 ErrorKind::IPC => write!(f, "IPC"),
59 ErrorKind::FileSystem => write!(f, "FileSystem"),
60 ErrorKind::Configuration => write!(f, "Configuration"),
61 ErrorKind::Service => write!(f, "Service"),
62 ErrorKind::Provider => write!(f, "Provider"),
63 ErrorKind::Other => write!(f, "Other"),
64 }
65 }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ErrorContext {
71 pub message:String,
72 pub kind:ErrorKind,
73 pub severity:ErrorSeverity,
74 pub operation:Option<String>,
75 pub component:Option<String>,
76}
77
78impl ErrorContext {
79 pub fn new(message:impl Into<String>) -> Self {
80 Self {
81 message:message.into(),
82 kind:ErrorKind::Other,
83 severity:ErrorSeverity::Error,
84 operation:None,
85 component:None,
86 }
87 }
88
89 pub fn with_kind(mut self, kind:ErrorKind) -> Self {
90 self.kind = kind;
91 self
92 }
93
94 pub fn with_severity(mut self, severity:ErrorSeverity) -> Self {
95 self.severity = severity;
96 self
97 }
98
99 pub fn with_operation(mut self, operation:impl Into<String>) -> Self {
100 self.operation = Some(operation.into());
101 self
102 }
103
104 pub fn with_component(mut self, component:impl Into<String>) -> Self {
105 self.component = Some(component.into());
106 self
107 }
108}
109
110impl fmt::Display for ErrorContext {
111 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "[{}][{}] {}", self.kind, self.severity, self.message)
113 }
114}
115
116#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct MountainError {
119 pub context:ErrorContext,
120 pub source:Option<String>,
121 pub stack_trace:Option<String>,
122}
123
124impl MountainError {
125 pub fn new(context:ErrorContext) -> Self { Self { context, source:None, stack_trace:None } }
126
127 pub fn with_source(mut self, source:impl Into<String>) -> Self {
128 self.source = Some(source.into());
129 self
130 }
131
132 pub fn with_stack_trace(mut self, stack_trace:impl Into<String>) -> Self {
133 self.stack_trace = Some(stack_trace.into());
134 self
135 }
136
137 pub fn message(&self) -> &str { &self.context.message }
138
139 pub fn kind(&self) -> ErrorKind { self.context.kind }
140
141 pub fn severity(&self) -> ErrorSeverity { self.context.severity }
142
143 pub fn is_critical(&self) -> bool { self.context.severity == ErrorSeverity::Critical }
144}
145
146impl fmt::Display for MountainError {
147 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
148 write!(f, "{}", self.context)?;
149 if let Some(source) = &self.source {
150 write!(f, " ({})", source)?;
151 }
152 Ok(())
153 }
154}
155
156impl StdError for MountainError {}
157
158impl From<ErrorContext> for MountainError {
159 fn from(context:ErrorContext) -> Self { Self::new(context) }
160}
161
162pub type Result<T> = std::result::Result<T, MountainError>;