headless_lms_utils/error/
util_error.rs1use std::fmt::Display;
6
7use backtrace::Backtrace;
8use tracing_error::SpanTrace;
9
10use super::backend_error::BackendError;
11
12pub type UtilResult<T> = Result<T, UtilError>;
18
19#[derive(Debug)]
21pub enum UtilErrorType {
22 UrlParse,
23 Walkdir,
24 StripPrefix,
25 TokioIo,
26 SerdeJson,
27 CloudStorage,
28 Other,
29 Unavailable,
30 DeserializationError,
31 TmcHttpError,
32 TmcErrorResponse,
33}
34
35#[derive(Debug)]
87pub struct UtilError {
88 error_type: <UtilError as BackendError>::ErrorType,
89 message: String,
90 source: Option<anyhow::Error>,
92 span_trace: Box<SpanTrace>,
94 backtrace: Box<Backtrace>,
96}
97
98impl std::error::Error for UtilError {
99 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
100 self.source.as_ref().and_then(|o| o.source())
101 }
102
103 fn cause(&self) -> Option<&dyn std::error::Error> {
104 self.source()
105 }
106}
107
108impl Display for UtilError {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 write!(f, "UtilError {:?} {:?}", self.error_type, self.message)
111 }
112}
113
114impl BackendError for UtilError {
115 type ErrorType = UtilErrorType;
116
117 fn new<M: Into<String>, S: Into<Option<anyhow::Error>>>(
118 error_type: Self::ErrorType,
119 message: M,
120 source_error: S,
121 ) -> Self {
122 Self::new_with_traces(
123 error_type,
124 message,
125 source_error,
126 Backtrace::new(),
127 SpanTrace::capture(),
128 )
129 }
130
131 fn backtrace(&self) -> Option<&Backtrace> {
132 Some(&self.backtrace)
133 }
134
135 fn error_type(&self) -> &Self::ErrorType {
136 &self.error_type
137 }
138
139 fn message(&self) -> &str {
140 &self.message
141 }
142
143 fn span_trace(&self) -> &SpanTrace {
144 &self.span_trace
145 }
146
147 fn new_with_traces<M: Into<String>, S: Into<Option<anyhow::Error>>>(
148 error_type: Self::ErrorType,
149 message: M,
150 source_error: S,
151 backtrace: Backtrace,
152 span_trace: SpanTrace,
153 ) -> Self {
154 Self {
155 error_type,
156 message: message.into(),
157 source: source_error.into(),
158 span_trace: Box::new(span_trace),
159 backtrace: Box::new(backtrace),
160 }
161 }
162}
163
164impl From<url::ParseError> for UtilError {
165 fn from(source: url::ParseError) -> Self {
166 UtilError::new(
167 UtilErrorType::UrlParse,
168 source.to_string(),
169 Some(source.into()),
170 )
171 }
172}
173
174impl From<walkdir::Error> for UtilError {
175 fn from(source: walkdir::Error) -> Self {
176 UtilError::new(
177 UtilErrorType::Walkdir,
178 source.to_string(),
179 Some(source.into()),
180 )
181 }
182}
183
184impl From<std::path::StripPrefixError> for UtilError {
185 fn from(source: std::path::StripPrefixError) -> Self {
186 UtilError::new(
187 UtilErrorType::StripPrefix,
188 source.to_string(),
189 Some(source.into()),
190 )
191 }
192}
193
194impl From<tokio::io::Error> for UtilError {
195 fn from(source: tokio::io::Error) -> Self {
196 UtilError::new(
197 UtilErrorType::TokioIo,
198 source.to_string(),
199 Some(source.into()),
200 )
201 }
202}
203
204impl From<serde_json::Error> for UtilError {
205 fn from(source: serde_json::Error) -> Self {
206 UtilError::new(
207 UtilErrorType::SerdeJson,
208 source.to_string(),
209 Some(source.into()),
210 )
211 }
212}
213
214impl From<cloud_storage::Error> for UtilError {
215 fn from(source: cloud_storage::Error) -> Self {
216 UtilError::new(
217 UtilErrorType::CloudStorage,
218 source.to_string(),
219 Some(source.into()),
220 )
221 }
222}
223
224impl From<anyhow::Error> for UtilError {
225 fn from(err: anyhow::Error) -> UtilError {
226 Self::new(UtilErrorType::Other, err.to_string(), Some(err))
227 }
228}