Skip to main content

eyre/
context.rs

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