eyre/
context.rs

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