1 | use crate::error::ContextError; |
2 | use crate::{ContextCompat, Report, StdError, WrapErr}; |
3 | use core::fmt::{self, Debug, Display, Write}; |
4 | |
5 | #[cfg (backtrace)] |
6 | use std::backtrace::Backtrace; |
7 | |
8 | mod 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 | |
40 | impl<T, E> WrapErr<T, E> for Result<T, E> |
41 | where |
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 | |
81 | impl<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 | |
119 | impl<D, E> Debug for ContextError<D, E> |
120 | where |
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 | |
132 | impl<D, E> Display for ContextError<D, E> |
133 | where |
134 | D: Display, |
135 | { |
136 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
137 | Display::fmt(&self.msg, f) |
138 | } |
139 | } |
140 | |
141 | impl<D, E> StdError for ContextError<D, E> |
142 | where |
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 | |
156 | impl<D> StdError for ContextError<D, Report> |
157 | where |
158 | D: Display, |
159 | { |
160 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
161 | Some(self.error.inner.error()) |
162 | } |
163 | } |
164 | |
165 | struct Quoted<D>(D); |
166 | |
167 | impl<D> Debug for Quoted<D> |
168 | where |
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 | |
179 | impl 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 | |
185 | pub(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 | |