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