Coverage Report

Created: 2025-02-07 03:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}