1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub enum Either<L, R> {
32 Left(L),
34 Right(R),
36}
37
38impl<L, R> Either<L, R> {
39 pub fn is_left(&self) -> bool {
41 matches!(self, Either::Left(_))
42 }
43
44 pub fn is_right(&self) -> bool {
46 matches!(self, Either::Right(_))
47 }
48
49 pub fn left(self) -> Option<L> {
51 match self {
52 Either::Left(l) => Some(l),
53 Either::Right(_) => None,
54 }
55 }
56
57 pub fn right(self) -> Option<R> {
59 match self {
60 Either::Left(_) => None,
61 Either::Right(r) => Some(r),
62 }
63 }
64
65 pub fn map_left<T, F: FnOnce(L) -> T>(self, f: F) -> Either<T, R> {
67 match self {
68 Either::Left(l) => Either::Left(f(l)),
69 Either::Right(r) => Either::Right(r),
70 }
71 }
72
73 pub fn map_right<T, F: FnOnce(R) -> T>(self, f: F) -> Either<L, T> {
75 match self {
76 Either::Left(l) => Either::Left(l),
77 Either::Right(r) => Either::Right(f(r)),
78 }
79 }
80
81 pub fn as_ref(&self) -> Either<&L, &R> {
83 match self {
84 Either::Left(l) => Either::Left(l),
85 Either::Right(r) => Either::Right(r),
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::Either;
93
94 #[test]
95 fn construction_and_match() {
96 let l: Either<i32, f64> = Either::Left(3);
97 let r: Either<i32, f64> = Either::Right(2.5);
98
99 match l {
100 Either::Left(v) => assert_eq!(v, 3),
101 Either::Right(_) => panic!("expected Left"),
102 }
103 match r {
104 Either::Left(_) => panic!("expected Right"),
105 Either::Right(v) => assert!((v - 2.5).abs() < f64::EPSILON),
106 }
107 }
108
109 #[test]
110 fn predicates_and_extractors() {
111 let l: Either<i32, &str> = Either::Left(1);
112 let r: Either<i32, &str> = Either::Right("x");
113
114 assert!(l.is_left());
115 assert!(!l.is_right());
116 assert!(r.is_right());
117 assert!(!r.is_left());
118
119 assert_eq!(l.left(), Some(1));
120 assert_eq!(l.right(), None);
121 assert_eq!(r.left(), None);
122 assert_eq!(r.right(), Some("x"));
123 }
124
125 #[test]
126 fn map_left_and_map_right() {
127 let l: Either<i32, &str> = Either::Left(10);
128 let r: Either<i32, &str> = Either::Right("y");
129
130 assert_eq!(l.map_left(|v| v * 2), Either::Left(20));
131 assert_eq!(l.map_right(str::len), Either::Left(10));
132 assert_eq!(r.map_left(|v| v * 2), Either::Right("y"));
133 assert_eq!(r.map_right(str::len), Either::Right(1));
134 }
135
136 #[test]
137 fn as_ref_and_derives() {
138 let l: Either<i32, &str> = Either::Left(5);
139 let copied = l; assert_eq!(l, copied); assert_eq!(l.as_ref(), Either::Left(&5));
142 let cloned = l.clone(); assert_eq!(format!("{cloned:?}"), "Left(5)"); }
145}