anyhow/
context.rs

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 core::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(any(feature = "std", not(anyhow_no_core_error)))]
19    impl<E> StdError for E
20    where
21        E: crate::StdError + 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::construct_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) => Ok(ok),
54            Err(error) => 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) => Ok(ok),
65            Err(error) => 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) => Ok(ok),
99            None => Err(Error::construct_from_display(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) => Ok(ok),
110            None => Err(Error::construct_from_display(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.debug_struct("Error")
122            .field("context", &Quoted(&self.context))
123            .field("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}