src/error.rs@main
raw
1use std::{convert, fmt};
2
3use tracing_error::SpanTrace;
4
5pub type Result<T, E = Error> = std::result::Result<T, E>;
6
7#[must_use]
8pub struct Error {
9 span_trace: SpanTrace,
10
11 inner: anyhow::Error,
12}
13
14impl Error {
15 pub fn new(inner: anyhow::Error) -> Self {
16 let span_trace = SpanTrace::capture();
17
18 Self { span_trace, inner }
19 }
20
21 pub fn context<C>(self, context: C) -> Self
22 where
23 C: fmt::Display + Send + Sync + 'static,
24 {
25 let inner = self.inner.context(context);
26
27 Self { inner, ..self }
28 }
29}
30
31impl fmt::Display for Error {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 fmt::Display::fmt(&self.inner, f)
34 }
35}
36
37impl fmt::Debug for Error {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 if f.alternate() {
40 return f
41 .debug_struct("Error")
42 .field("inner", &self.inner)
43 .field("span_trace", &self.span_trace)
44 .finish();
45 }
46
47 write!(f, "{:?}\n\nSpan traces:\n{}", self.inner, self.span_trace)
48 }
49}
50
51impl<E> From<E> for Error
52where
53 E: std::error::Error + Send + Sync + 'static,
54{
55 fn from(error: E) -> Self {
56 let span_trace = SpanTrace::capture();
57 let inner = anyhow::Error::from(error);
58 Self { span_trace, inner }
59 }
60}
61
62impl tracing_error::ExtractSpanTrace for Error {
63 fn span_trace(&self) -> Option<&SpanTrace> {
64 Some(&self.span_trace)
65 }
66}
67
68pub trait Context<T, E> {
69 fn context<C>(self, context: C) -> Result<T, Error>
70 where
71 C: fmt::Display + Send + Sync + 'static;
72
73 fn with_context<C, F>(self, f: F) -> Result<T, Error>
74 where
75 C: fmt::Display + Send + Sync + 'static,
76 F: FnOnce() -> C;
77}
78
79impl<T> Context<T, convert::Infallible> for Option<T> {
80 fn context<C>(self, context: C) -> Result<T, Error>
81 where
82 C: fmt::Display + Send + Sync + 'static,
83 {
84 self.map_or_else(
85 || Err(must_use(Error::new(::anyhow::format_err!("{context}")))),
86 |ok| Ok(ok),
87 )
88 }
89
90 fn with_context<C, F>(self, context: F) -> Result<T, Error>
91 where
92 C: fmt::Display + Send + Sync + 'static,
93 F: FnOnce() -> C,
94 {
95 self.map_or_else(
96 || Err(must_use(Error::new(::anyhow::format_err!("{}", context())))),
97 |ok| Ok(ok),
98 )
99 }
100}
101
102impl<T, E> Context<T, E> for Result<T, E>
103where
104 E: std::error::Error + Send + Sync + 'static,
105{
106 fn context<C>(self, context: C) -> Result<T, Error>
107 where
108 C: fmt::Display + Send + Sync + 'static,
109 {
110 match self {
111 Ok(ok) => Ok(ok),
112 Err(error) => Err(Error::new(anyhow::Error::new(error).context(context))),
113 }
114 }
115
116 fn with_context<C, F>(self, context: F) -> Result<T, Error>
117 where
118 C: fmt::Display + Send + Sync + 'static,
119 F: FnOnce() -> C,
120 {
121 match self {
122 Ok(ok) => Ok(ok),
123 Err(error) => Err(Error::new(anyhow::Error::new(error).context(context()))),
124 }
125 }
126}
127
128impl<T> Context<T, Error> for Result<T, Error> {
129 fn context<C>(self, context: C) -> Self
130 where
131 C: fmt::Display + Send + Sync + 'static,
132 {
133 match self {
134 Ok(ok) => Ok(ok),
135 Err(error) => Err(error.context(context)),
136 }
137 }
138
139 fn with_context<C, F>(self, context: F) -> Self
140 where
141 C: fmt::Display + Send + Sync + 'static,
142 F: FnOnce() -> C,
143 {
144 match self {
145 Ok(ok) => Ok(ok),
146 Err(error) => Err(error.context(context())),
147 }
148 }
149}
150
151#[doc(hidden)]
152#[inline]
153#[cold]
154pub const fn must_use(error: Error) -> Error {
155 error
156}
157