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