1 | use crate::error::ContextError; |
2 | use crate::{Context, Error, StdError}; |
3 | use core::convert::Infallible; |
4 | use core::fmt::{self, Debug, Display, Write}; |
5 | |
6 | #[cfg (backtrace)] |
7 | use std::error::Request; |
8 | |
9 | mod ext { |
10 | use super::*; |
11 | |
12 | pub trait StdError { |
13 | fn ext_context<C>(self, context: C) -> Error |
14 | where |
15 | C: Display + Send + Sync + 'static; |
16 | } |
17 | |
18 | #[cfg (feature = "std" )] |
19 | impl<E> StdError for E |
20 | where |
21 | E: std::error::Error + Send + Sync + 'static, |
22 | { |
23 | fn ext_context<C>(self, context: C) -> Error |
24 | where |
25 | C: Display + Send + Sync + 'static, |
26 | { |
27 | let backtrace = backtrace_if_absent!(&self); |
28 | Error::from_context(context, self, backtrace) |
29 | } |
30 | } |
31 | |
32 | impl StdError for Error { |
33 | fn ext_context<C>(self, context: C) -> Error |
34 | where |
35 | C: Display + Send + Sync + 'static, |
36 | { |
37 | self.context(context) |
38 | } |
39 | } |
40 | } |
41 | |
42 | impl<T, E> Context<T, E> for Result<T, E> |
43 | where |
44 | E: ext::StdError + Send + Sync + 'static, |
45 | { |
46 | fn context<C>(self, context: C) -> Result<T, Error> |
47 | where |
48 | C: Display + Send + Sync + 'static, |
49 | { |
50 | // Not using map_err to save 2 useless frames off the captured backtrace |
51 | // in ext_context. |
52 | match self { |
53 | Ok(ok: T) => Ok(ok), |
54 | Err(error: E) => Err(error.ext_context(context)), |
55 | } |
56 | } |
57 | |
58 | fn with_context<C, F>(self, context: F) -> Result<T, Error> |
59 | where |
60 | C: Display + Send + Sync + 'static, |
61 | F: FnOnce() -> C, |
62 | { |
63 | match self { |
64 | Ok(ok: T) => Ok(ok), |
65 | Err(error: E) => Err(error.ext_context(context())), |
66 | } |
67 | } |
68 | } |
69 | |
70 | /// ``` |
71 | /// # type T = (); |
72 | /// # |
73 | /// use anyhow::{Context, Result}; |
74 | /// |
75 | /// fn maybe_get() -> Option<T> { |
76 | /// # const IGNORE: &str = stringify! { |
77 | /// ... |
78 | /// # }; |
79 | /// # unimplemented!() |
80 | /// } |
81 | /// |
82 | /// fn demo() -> Result<()> { |
83 | /// let t = maybe_get().context("there is no T" )?; |
84 | /// # const IGNORE: &str = stringify! { |
85 | /// ... |
86 | /// # }; |
87 | /// # unimplemented!() |
88 | /// } |
89 | /// ``` |
90 | impl<T> Context<T, Infallible> for Option<T> { |
91 | fn context<C>(self, context: C) -> Result<T, Error> |
92 | where |
93 | C: Display + Send + Sync + 'static, |
94 | { |
95 | // Not using ok_or_else to save 2 useless frames off the captured |
96 | // backtrace. |
97 | match self { |
98 | Some(ok: T) => Ok(ok), |
99 | None => Err(Error::from_display(message:context, backtrace!())), |
100 | } |
101 | } |
102 | |
103 | fn with_context<C, F>(self, context: F) -> Result<T, Error> |
104 | where |
105 | C: Display + Send + Sync + 'static, |
106 | F: FnOnce() -> C, |
107 | { |
108 | match self { |
109 | Some(ok: T) => Ok(ok), |
110 | None => Err(Error::from_display(message:context(), backtrace!())), |
111 | } |
112 | } |
113 | } |
114 | |
115 | impl<C, E> Debug for ContextError<C, E> |
116 | where |
117 | C: Display, |
118 | E: Debug, |
119 | { |
120 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
121 | f&mut DebugStruct<'_, '_>.debug_struct("Error" ) |
122 | .field("context" , &Quoted(&self.context)) |
123 | .field(name:"source" , &self.error) |
124 | .finish() |
125 | } |
126 | } |
127 | |
128 | impl<C, E> Display for ContextError<C, E> |
129 | where |
130 | C: Display, |
131 | { |
132 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
133 | Display::fmt(&self.context, f) |
134 | } |
135 | } |
136 | |
137 | impl<C, E> StdError for ContextError<C, E> |
138 | where |
139 | C: Display, |
140 | E: StdError + 'static, |
141 | { |
142 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
143 | Some(&self.error) |
144 | } |
145 | |
146 | #[cfg (backtrace)] |
147 | fn provide<'a>(&'a self, request: &mut Request<'a>) { |
148 | StdError::provide(&self.error, request); |
149 | } |
150 | } |
151 | |
152 | impl<C> StdError for ContextError<C, Error> |
153 | where |
154 | C: Display, |
155 | { |
156 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
157 | Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) |
158 | } |
159 | |
160 | #[cfg (backtrace)] |
161 | fn provide<'a>(&'a self, request: &mut Request<'a>) { |
162 | Error::provide(&self.error, request); |
163 | } |
164 | } |
165 | |
166 | struct Quoted<C>(C); |
167 | |
168 | impl<C> Debug for Quoted<C> |
169 | where |
170 | C: Display, |
171 | { |
172 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
173 | formatter.write_char('"' )?; |
174 | Quoted(&mut *formatter).write_fmt(format_args!(" {}" , self.0))?; |
175 | formatter.write_char('"' )?; |
176 | Ok(()) |
177 | } |
178 | } |
179 | |
180 | impl Write for Quoted<&mut fmt::Formatter<'_>> { |
181 | fn write_str(&mut self, s: &str) -> fmt::Result { |
182 | Display::fmt(&s.escape_debug(), self.0) |
183 | } |
184 | } |
185 | |
186 | pub(crate) mod private { |
187 | use super::*; |
188 | |
189 | pub trait Sealed {} |
190 | |
191 | impl<T, E> Sealed for Result<T, E> where E: ext::StdError {} |
192 | impl<T> Sealed for Option<T> {} |
193 | } |
194 | |