• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::backtrace::Backtrace;
8 
9 mod ext {
10     use super::*;
11 
12     pub trait StdError {
ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static13         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     {
ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static,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 {
ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static,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 {
context<C>(self, context: C) -> Result<T, Error> where C: Display + Send + Sync + 'static,46     fn context<C>(self, context: C) -> Result<T, Error>
47     where
48         C: Display + Send + Sync + 'static,
49     {
50         self.map_err(|error| error.ext_context(context))
51     }
52 
with_context<C, F>(self, context: F) -> Result<T, Error> where C: Display + Send + Sync + 'static, F: FnOnce() -> C,53     fn with_context<C, F>(self, context: F) -> Result<T, Error>
54     where
55         C: Display + Send + Sync + 'static,
56         F: FnOnce() -> C,
57     {
58         self.map_err(|error| error.ext_context(context()))
59     }
60 }
61 
62 /// ```
63 /// # type T = ();
64 /// #
65 /// use anyhow::{Context, Result};
66 ///
67 /// fn maybe_get() -> Option<T> {
68 ///     # const IGNORE: &str = stringify! {
69 ///     ...
70 ///     # };
71 ///     # unimplemented!()
72 /// }
73 ///
74 /// fn demo() -> Result<()> {
75 ///     let t = maybe_get().context("there is no T")?;
76 ///     # const IGNORE: &str = stringify! {
77 ///     ...
78 ///     # };
79 ///     # unimplemented!()
80 /// }
81 /// ```
82 impl<T> Context<T, Infallible> for Option<T> {
context<C>(self, context: C) -> Result<T, Error> where C: Display + Send + Sync + 'static,83     fn context<C>(self, context: C) -> Result<T, Error>
84     where
85         C: Display + Send + Sync + 'static,
86     {
87         self.ok_or_else(|| Error::from_display(context, backtrace!()))
88     }
89 
with_context<C, F>(self, context: F) -> Result<T, Error> where C: Display + Send + Sync + 'static, F: FnOnce() -> C,90     fn with_context<C, F>(self, context: F) -> Result<T, Error>
91     where
92         C: Display + Send + Sync + 'static,
93         F: FnOnce() -> C,
94     {
95         self.ok_or_else(|| Error::from_display(context(), backtrace!()))
96     }
97 }
98 
99 impl<C, E> Debug for ContextError<C, E>
100 where
101     C: Display,
102     E: Debug,
103 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result104     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105         f.debug_struct("Error")
106             .field("context", &Quoted(&self.context))
107             .field("source", &self.error)
108             .finish()
109     }
110 }
111 
112 impl<C, E> Display for ContextError<C, E>
113 where
114     C: Display,
115 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result116     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117         Display::fmt(&self.context, f)
118     }
119 }
120 
121 impl<C, E> StdError for ContextError<C, E>
122 where
123     C: Display,
124     E: StdError + 'static,
125 {
126     #[cfg(backtrace)]
backtrace(&self) -> Option<&Backtrace>127     fn backtrace(&self) -> Option<&Backtrace> {
128         self.error.backtrace()
129     }
130 
source(&self) -> Option<&(dyn StdError + 'static)>131     fn source(&self) -> Option<&(dyn StdError + 'static)> {
132         Some(&self.error)
133     }
134 }
135 
136 impl<C> StdError for ContextError<C, Error>
137 where
138     C: Display,
139 {
140     #[cfg(backtrace)]
backtrace(&self) -> Option<&Backtrace>141     fn backtrace(&self) -> Option<&Backtrace> {
142         Some(self.error.backtrace())
143     }
144 
source(&self) -> Option<&(dyn StdError + 'static)>145     fn source(&self) -> Option<&(dyn StdError + 'static)> {
146         Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) })
147     }
148 }
149 
150 struct Quoted<C>(C);
151 
152 impl<C> Debug for Quoted<C>
153 where
154     C: Display,
155 {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result156     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
157         formatter.write_char('"')?;
158         Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?;
159         formatter.write_char('"')?;
160         Ok(())
161     }
162 }
163 
164 impl Write for Quoted<&mut fmt::Formatter<'_>> {
write_str(&mut self, s: &str) -> fmt::Result165     fn write_str(&mut self, s: &str) -> fmt::Result {
166         Display::fmt(&s.escape_debug(), self.0)
167     }
168 }
169 
170 pub(crate) mod private {
171     use super::*;
172 
173     pub trait Sealed {}
174 
175     impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
176     impl<T> Sealed for Option<T> {}
177 }
178