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}