/home/runner/work/bare_err_tree/bare_err_tree/bare_err_tree/src/flex.rs
Line | Count | Source |
1 | | /* |
2 | | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at https://mozilla.org/MPL/2.0/. |
5 | | */ |
6 | | |
7 | | use core::error::Error; |
8 | | |
9 | | use crate::{AsErrTree, ErrTree}; |
10 | | |
11 | | /// Provides a default [`AsErrTree`] for arbitrary [`Error`]s. |
12 | | /// |
13 | | /// The primary purpose of this type is to enable `&E` to have a |
14 | | /// `&dyn AsErrTree` cast without an intermediate `&dyn Error` and without |
15 | | /// an [`AsErrTree`] blanket impl. This requires an unsafe cast via the |
16 | | /// transparent repr guarantees. |
17 | | /// |
18 | | /// ```rust |
19 | 1 | /// use bare_err_tree::{WrapErr, AsErrTree}; |
20 | | /// |
21 | | /// let err = std::io::Error::last_os_error(); |
22 | 1 | /// let err_ref = &err; |
23 | 1 | /// |
24 | 1 | /// let wrapped = WrapErr::wrap(err_ref); |
25 | 1 | /// let as_dyn = wrapped as &dyn AsErrTree; |
26 | 1 | /// |
27 | 1 | /// let alt_dyn = WrapErr::tree(err_ref); |
28 | 1 | /// ``` |
29 | 1 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
30 | | #[repr(transparent)] |
31 | | pub struct WrapErr<E: Error + ?Sized>(pub E); |
32 | | |
33 | | impl<E: Error + ?Sized> From<&E> for &WrapErr<E> { |
34 | 14 | fn from(value: &E) -> Self { |
35 | 14 | unsafe { &*(value as *const E as *const WrapErr<E>) } |
36 | 14 | } |
37 | | } |
38 | | |
39 | | impl<E: Error + ?Sized> WrapErr<E> { |
40 | 14 | pub fn wrap(err: &E) -> &Self { |
41 | 14 | err.into() |
42 | 14 | } |
43 | | } |
44 | | |
45 | | impl<E: Error> WrapErr<E> { |
46 | 13 | pub fn tree(err: &E) -> &dyn AsErrTree { |
47 | 13 | Self::wrap(err) as &dyn AsErrTree |
48 | 13 | } |
49 | | } |
50 | | |
51 | | impl<E: Error> AsErrTree for WrapErr<E> { |
52 | 6 | fn as_err_tree(&self, func: &mut dyn FnMut(ErrTree<'_>)) { |
53 | 6 | match self.0.source() { |
54 | 0 | Some(e) => (func)(ErrTree::no_pkg( |
55 | 0 | &self.0, |
56 | 0 | &mut core::iter::once(&e as &dyn AsErrTree), |
57 | 0 | )), |
58 | 6 | None => (func)(ErrTree::no_pkg(&self.0, &mut core::iter::empty())), |
59 | | } |
60 | 6 | } |
61 | | } |