1use crate::error::ContextError;
2use crate::{Context, Error, StdError};
3use core::convert::Infallible;
4use core::fmt::{self, Debug, Display, Write};
5
6#[cfg(error_generic_member_access)]
7use std::error::Request;
8
9mod 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
42impl<T, E> Context<T, E> for Result<T, E>
43where
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/// ```
90impl<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
115impl<C, E> Debug for ContextError<C, E>
116where
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
128impl<C, E> Display for ContextError<C, E>
129where
130 C: Display,
131{
132 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133 Display::fmt(&self.context, f)
134 }
135}
136
137impl<C, E> StdError for ContextError<C, E>
138where
139 C: Display,
140 E: StdError + 'static,
141{
142 fn source(&self) -> Option<&(dyn StdError + 'static)> {
143 Some(&self.error)
144 }
145
146 #[cfg(error_generic_member_access)]
147 fn provide<'a>(&'a self, request: &mut Request<'a>) {
148 StdError::provide(&self.error, request);
149 }
150}
151
152impl<C> StdError for ContextError<C, Error>
153where
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(error_generic_member_access)]
161 fn provide<'a>(&'a self, request: &mut Request<'a>) {
162 Error::provide(&self.error, request);
163 }
164}
165
166struct Quoted<C>(C);
167
168impl<C> Debug for Quoted<C>
169where
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
180impl 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
186pub(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