1use std::any::Any;
16use std::fmt::{Debug, Formatter};
17use std::sync::Arc;
18
19use snafu::{FromString, Snafu};
20
21use crate::status_code::StatusCode;
22
23pub trait ErrorExt: StackError {
25 fn status_code(&self) -> StatusCode {
27 StatusCode::Unknown
28 }
29
30 fn as_any(&self) -> &dyn Any;
33
34 fn output_msg(&self) -> String
35 where
36 Self: Sized,
37 {
38 match self.status_code() {
39 StatusCode::Unknown | StatusCode::Internal => {
40 format!("Internal error: {}", self.status_code() as u32)
42 }
43 _ => {
44 let error = self.last();
45 if let Some(external_error) = error.source() {
46 let external_root = external_error.sources().last().unwrap();
47
48 if error.transparent() {
49 format!("{external_root}")
50 } else {
51 format!("{error}: {external_root}")
52 }
53 } else {
54 format!("{error}")
55 }
56 }
57 }
58 }
59
60 fn root_cause(&self) -> Option<&dyn std::error::Error>
62 where
63 Self: Sized,
64 {
65 let error = self.last();
66 if let Some(external_error) = error.source() {
67 let external_root = external_error.sources().last().unwrap();
68 Some(external_root)
69 } else {
70 None
71 }
72 }
73}
74
75pub trait StackError: std::error::Error {
76 fn debug_fmt(&self, layer: usize, buf: &mut Vec<String>);
77
78 fn next(&self) -> Option<&dyn StackError>;
79
80 fn last(&self) -> &dyn StackError
81 where
82 Self: Sized,
83 {
84 let Some(mut result) = self.next() else {
85 return self;
86 };
87 while let Some(err) = result.next() {
88 result = err;
89 }
90 result
91 }
92
93 fn transparent(&self) -> bool {
98 false
99 }
100}
101
102impl<T: ?Sized + StackError> StackError for Arc<T> {
103 fn debug_fmt(&self, layer: usize, buf: &mut Vec<String>) {
104 self.as_ref().debug_fmt(layer, buf)
105 }
106
107 fn next(&self) -> Option<&dyn StackError> {
108 self.as_ref().next()
109 }
110}
111
112impl<T: StackError> StackError for Box<T> {
113 fn debug_fmt(&self, layer: usize, buf: &mut Vec<String>) {
114 self.as_ref().debug_fmt(layer, buf)
115 }
116
117 fn next(&self) -> Option<&dyn StackError> {
118 self.as_ref().next()
119 }
120}
121
122pub type WhateverResult<T> = Result<T, Whatever>;
126
127#[derive(Snafu)]
128#[snafu(display("{inner}"))]
129pub struct Whatever {
130 inner: snafu::Whatever,
131}
132
133impl Debug for Whatever {
134 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135 write!(f, "{}", self.inner)
136 }
137}
138
139impl<E: ErrorExt> From<E> for Whatever {
140 fn from(e: E) -> Self {
141 Self {
142 inner: FromString::without_source(format!("{e:?}")),
143 }
144 }
145}
146
147impl From<String> for Whatever {
148 fn from(s: String) -> Self {
149 Self {
150 inner: FromString::without_source(s),
151 }
152 }
153}
154
155pub struct BoxedError {
157 inner: Box<dyn crate::ext::ErrorExt + Send + Sync>,
158}
159
160impl BoxedError {
161 pub fn new<E: crate::ext::ErrorExt + Send + Sync + 'static>(err: E) -> Self {
162 Self {
163 inner: Box::new(err),
164 }
165 }
166
167 pub fn into_inner(self) -> Box<dyn crate::ext::ErrorExt + Send + Sync> {
168 self.inner
169 }
170}
171
172impl std::fmt::Debug for BoxedError {
173 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174 let mut buf = vec![];
175 self.debug_fmt(0, &mut buf);
176 write!(f, "{}", buf.join("\n"))
177 }
178}
179
180impl std::fmt::Display for BoxedError {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 write!(f, "{}", self.inner)
183 }
184}
185
186impl std::error::Error for BoxedError {
187 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
188 self.inner.source()
189 }
190}
191
192impl crate::ext::ErrorExt for BoxedError {
193 fn status_code(&self) -> crate::status_code::StatusCode {
194 self.inner.status_code()
195 }
196
197 fn as_any(&self) -> &dyn std::any::Any {
198 self.inner.as_any()
199 }
200}
201
202impl crate::snafu::ErrorCompat for BoxedError {
205 fn backtrace(&self) -> Option<&crate::snafu::Backtrace> {
206 None
207 }
208}
209
210impl StackError for BoxedError {
211 fn debug_fmt(&self, layer: usize, buf: &mut Vec<String>) {
212 self.inner.debug_fmt(layer, buf)
213 }
214
215 fn next(&self) -> Option<&dyn StackError> {
216 self.inner.next()
217 }
218}
219
220#[derive(Debug)]
222pub struct PlainError {
223 msg: String,
224 status_code: StatusCode,
225}
226
227impl PlainError {
228 pub fn new(msg: String, status_code: StatusCode) -> Self {
229 Self { msg, status_code }
230 }
231}
232
233impl std::fmt::Display for PlainError {
234 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235 write!(f, "{}", self.msg)
236 }
237}
238
239impl std::error::Error for PlainError {
240 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
241 None
242 }
243}
244
245impl crate::ext::ErrorExt for PlainError {
246 fn status_code(&self) -> crate::status_code::StatusCode {
247 self.status_code
248 }
249
250 fn as_any(&self) -> &dyn std::any::Any {
251 self as _
252 }
253}
254
255impl StackError for PlainError {
256 fn debug_fmt(&self, layer: usize, buf: &mut Vec<String>) {
257 buf.push(format!("{}: {}", layer, self.msg))
258 }
259
260 fn next(&self) -> Option<&dyn StackError> {
261 None
262 }
263}