1use crate::error::ContextError;
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&mut DebugStruct<'_, '_>.debug_struct("Error")
126 .field("msg", &Quoted(&self.msg))
127 .field(name:"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(self.error.inner.error())
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}
193