Skip to main content

other_error/
either.rs

1
2use either::Either;
3use core::error::Error;
4use core::fmt::{Debug, Display};
5
6/// Error that is one of two possible error types.
7pub struct EitherError<L, R> {
8    inner: Either<L, R>,
9}
10
11impl<L, R> AsRef<Either<L, R>> for EitherError<L, R> {
12    fn as_ref(&self) -> &Either<L, R> {
13        &self.inner
14    }
15}
16
17impl<L, R> From<Either<L, R>> for EitherError<L, R> {
18    fn from(inner: Either<L, R>) -> Self {
19        Self::new(inner)
20    }
21}
22
23impl<L, R> EitherError<L, R> {
24    pub fn new(inner: Either<L, R>) -> Self {
25        Self { inner }
26    }
27    
28    pub fn into_inner(self) -> Either<L, R> {
29        self.inner
30    }
31}
32
33impl<L: Debug, R: Debug> Debug for EitherError<L, R> {
34    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35        match &self.inner {
36            Either::Left(err) => err.fmt(f),
37            Either::Right(err) => err.fmt(f),
38        }
39    }
40}
41
42impl<L: Display, R: Display> Display for EitherError<L, R> {
43    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44        match &self.inner {
45            Either::Left(err) => err.fmt(f),
46            Either::Right(err) => err.fmt(f),
47        }
48    }
49}
50
51impl<L, R> Error for EitherError<L, R> where L: Error, R: Error {
52    fn source(&self) -> Option<&(dyn Error + 'static)> {
53        match &self.inner {
54            Either::Left(err) => err.source(),
55            Either::Right(err) => err.source(),
56        }
57    }
58}
59
60#[cfg(all(test, feature = "alloc"))]
61mod tests {
62    extern crate alloc;
63    use super::*;
64    use alloc::format;
65
66    #[derive(Debug)]
67    struct LeftErr;
68    #[derive(Debug)]
69    struct RightErr;
70
71    impl Display for LeftErr {
72        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73            f.write_str("left")
74        }
75    }
76
77    impl Display for RightErr {
78        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79            f.write_str("right")
80        }
81    }
82
83    #[test]
84    fn left_formats_left() {
85        let err: EitherError<LeftErr, RightErr> = Either::Left(LeftErr).into();
86        assert_eq!(format!("{}", err), "left");
87        assert_eq!(format!("{:?}", err), "LeftErr");
88    }
89
90    #[test]
91    fn right_formats_right() {
92        let err: EitherError<LeftErr, RightErr> = Either::Right(RightErr).into();
93        assert_eq!(format!("{}", err), "right");
94        assert_eq!(format!("{:?}", err), "RightErr");
95    }
96
97    #[test]
98    fn into_inner_round_trips() {
99        let err = EitherError::<LeftErr, RightErr>::new(Either::Left(LeftErr));
100        assert!(matches!(err.into_inner(), Either::Left(LeftErr)));
101    }
102}