1use core::{fmt::Display, mem};
2
3use crate::{Error, StackableErrorTrait};
4
5pub trait StackableErr {
10 type Output;
11
12 fn stack(self) -> Self::Output;
14
15 fn stack_locationless(self) -> Self::Output;
17
18 fn stack_err<E: Display + Send + Sync + 'static>(self, e: E) -> Self::Output;
20
21 fn stack_err_with<E: Display + Send + Sync + 'static, F: FnOnce() -> E>(
23 self,
24 f: F,
25 ) -> Self::Output;
26
27 fn stack_err_locationless<E: Display + Send + Sync + 'static>(self, e: E) -> Self::Output;
29
30 fn stack_err_with_locationless<E: Display + Send + Sync + 'static, F: FnOnce() -> E>(
32 self,
33 f: F,
34 ) -> Self::Output;
35
36 fn wrap_err<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output;
39
40 fn wrap_err_with<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
43 self,
44 msg: F,
45 ) -> Self::Output;
46
47 fn context<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output;
50
51 fn with_context<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
54 self,
55 msg: F,
56 ) -> Self::Output;
57}
58
59#[track_caller]
110fn stack<E: Display + Send + Sync + 'static>(mut err: E) -> Error {
111 let tmp: &mut dyn StackableErrorTrait = &mut err;
112 if let Some(tmp) = tmp._as_any_mut().downcast_mut::<Error>() {
113 tmp.push();
114 mem::take(tmp)
117 } else {
118 Error::from_err(err)
119 }
120}
121
122fn stack_locationless<E: Display + Send + Sync + 'static>(mut err: E) -> Error {
123 let tmp: &mut dyn StackableErrorTrait = &mut err;
124 if let Some(tmp) = tmp._as_any_mut().downcast_mut::<Error>() {
125 mem::take(tmp)
126 } else {
127 Error::from_err_locationless(err)
128 }
129}
130
131#[track_caller]
132fn stack_err<E: Display + Send + Sync + 'static, E1: Display + Send + Sync + 'static>(
133 mut err: E,
134 e: E1,
135) -> Error {
136 let tmp: &mut dyn StackableErrorTrait = &mut err;
137 if let Some(tmp) = tmp._as_any_mut().downcast_mut::<Error>() {
138 tmp.push_err(e);
139 mem::take(tmp)
140 } else {
141 Error::from_err_locationless(err).add_err(e)
143 }
144}
145
146#[track_caller]
147fn stack_err_locationless<
148 E: Display + Send + Sync + 'static,
149 E1: Display + Send + Sync + 'static,
150>(
151 mut err: E,
152 e: E1,
153) -> Error {
154 let tmp: &mut dyn StackableErrorTrait = &mut err;
155 if let Some(tmp) = tmp._as_any_mut().downcast_mut::<Error>() {
156 tmp.push_err_locationless(e);
157 mem::take(tmp)
158 } else {
159 Error::from_err_locationless(err).add_err_locationless(e)
160 }
161}
162
163impl<T, E: Display + Send + Sync + 'static> StackableErr for core::result::Result<T, E> {
164 type Output = core::result::Result<T, Error>;
165
166 #[track_caller]
167 fn stack(self) -> Self::Output {
168 match self {
169 Ok(o) => Ok(o),
170 Err(err) => Err(stack(err)),
171 }
172 }
173
174 fn stack_locationless(self) -> Self::Output {
175 match self {
176 Ok(o) => Ok(o),
177 Err(err) => Err(stack_locationless(err)),
178 }
179 }
180
181 #[track_caller]
182 fn stack_err<E1: Display + Send + Sync + 'static>(self, e: E1) -> Self::Output {
183 match self {
184 Ok(o) => Ok(o),
185 Err(err) => Err(stack_err(err, e)),
186 }
187 }
188
189 #[track_caller]
190 fn stack_err_with<E1: Display + Send + Sync + 'static, F: FnOnce() -> E1>(
191 self,
192 f: F,
193 ) -> Self::Output {
194 match self {
195 Ok(o) => Ok(o),
196 Err(err) => Err(stack_err(err, f())),
197 }
198 }
199
200 fn stack_err_locationless<E1: Display + Send + Sync + 'static>(self, e: E1) -> Self::Output {
201 match self {
202 Ok(o) => Ok(o),
203 Err(err) => Err(stack_err_locationless(err, e)),
204 }
205 }
206
207 fn stack_err_with_locationless<E1: Display + Send + Sync + 'static, F: FnOnce() -> E1>(
208 self,
209 f: F,
210 ) -> Self::Output {
211 match self {
212 Ok(o) => Ok(o),
213 Err(err) => Err(stack_err_locationless(err, f())),
214 }
215 }
216
217 #[track_caller]
218 fn wrap_err<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output {
219 self.stack_err(msg)
220 }
221
222 #[track_caller]
223 fn wrap_err_with<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
224 self,
225 msg: F,
226 ) -> Self::Output {
227 self.stack_err_with(msg)
228 }
229
230 #[track_caller]
231 fn context<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output {
232 self.stack_err(msg)
233 }
234
235 #[track_caller]
236 fn with_context<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
237 self,
238 msg: F,
239 ) -> Self::Output {
240 self.stack_err_with(msg)
241 }
242}
243
244impl<T> StackableErr for Option<T> {
245 type Output = core::result::Result<T, Error>;
246
247 #[track_caller]
248 fn stack(self) -> Self::Output {
249 match self {
250 Some(o) => Ok(o),
251 None => Err(Error::new()),
252 }
253 }
254
255 fn stack_locationless(self) -> Self::Output {
256 match self {
257 Some(o) => Ok(o),
258 None => Err(Error::empty()),
259 }
260 }
261
262 #[track_caller]
263 fn stack_err<E1: Display + Send + Sync + 'static>(self, e: E1) -> Self::Output {
264 match self {
265 Some(o) => Ok(o),
266 None => Err(Error::from_err(e)),
267 }
268 }
269
270 #[track_caller]
271 fn stack_err_with<E1: Display + Send + Sync + 'static, F: FnOnce() -> E1>(
272 self,
273 f: F,
274 ) -> Self::Output {
275 match self {
276 Some(o) => Ok(o),
277 None => Err(Error::from_err(f())),
278 }
279 }
280
281 fn stack_err_locationless<E1: Display + Send + Sync + 'static>(self, e: E1) -> Self::Output {
282 match self {
283 Some(o) => Ok(o),
284 None => Err(Error::from_err_locationless(e)),
285 }
286 }
287
288 fn stack_err_with_locationless<E1: Display + Send + Sync + 'static, F: FnOnce() -> E1>(
289 self,
290 f: F,
291 ) -> Self::Output {
292 match self {
293 Some(o) => Ok(o),
294 None => Err(Error::from_err_locationless(f())),
295 }
296 }
297
298 #[track_caller]
299 fn wrap_err<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output {
300 self.stack_err(msg)
301 }
302
303 #[track_caller]
304 fn wrap_err_with<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
305 self,
306 msg: F,
307 ) -> Self::Output {
308 self.stack_err_with(msg)
309 }
310
311 #[track_caller]
312 fn context<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output {
313 self.stack_err(msg)
314 }
315
316 #[track_caller]
317 fn with_context<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
318 self,
319 msg: F,
320 ) -> Self::Output {
321 self.stack_err_with(msg)
322 }
323}
324
325impl StackableErr for Error {
326 type Output = core::result::Result<(), Error>;
327
328 #[track_caller]
329 fn stack(self) -> Self::Output {
330 Err(self.add())
331 }
332
333 fn stack_locationless(self) -> Self::Output {
334 Err(self)
335 }
336
337 #[track_caller]
338 fn stack_err<E1: Display + Send + Sync + 'static>(self, e: E1) -> Self::Output {
339 Err(self.add_err(e))
340 }
341
342 #[track_caller]
343 fn stack_err_with<E1: Display + Send + Sync + 'static, F: FnOnce() -> E1>(
344 self,
345 f: F,
346 ) -> Self::Output {
347 Err(self.add_err(f()))
348 }
349
350 fn stack_err_locationless<E1: Display + Send + Sync + 'static>(self, e: E1) -> Self::Output {
351 Err(self.add_err_locationless(e))
352 }
353
354 fn stack_err_with_locationless<E1: Display + Send + Sync + 'static, F: FnOnce() -> E1>(
355 self,
356 f: F,
357 ) -> Self::Output {
358 Err(self.add_err_locationless(f()))
359 }
360
361 #[track_caller]
362 fn wrap_err<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output {
363 self.stack_err(msg)
364 }
365
366 #[track_caller]
367 fn wrap_err_with<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
368 self,
369 msg: F,
370 ) -> Self::Output {
371 self.stack_err_with(msg)
372 }
373
374 #[track_caller]
375 fn context<D: Display + Send + Sync + 'static>(self, msg: D) -> Self::Output {
376 self.stack_err(msg)
377 }
378
379 #[track_caller]
380 fn with_context<D: Display + Send + Sync + 'static, F: FnOnce() -> D>(
381 self,
382 msg: F,
383 ) -> Self::Output {
384 self.stack_err_with(msg)
385 }
386}