ntex_util/future/
either.rs1use std::{error, fmt, future::Future, pin::Pin, task::Context, task::Poll};
2
3#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
6pub enum Either<A, B> {
7 Left(A),
9 Right(B),
11}
12
13impl<A, B> Either<A, B> {
14 fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
15 unsafe {
16 match self.get_unchecked_mut() {
17 Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
18 Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
19 }
20 }
21 }
22
23 #[inline]
24 pub fn is_left(&self) -> bool {
26 match *self {
27 Either::Left(_) => true,
28 Either::Right(_) => false,
29 }
30 }
31
32 #[inline]
33 pub fn is_right(&self) -> bool {
35 !self.is_left()
36 }
37
38 #[inline]
39 pub fn left(self) -> Option<A> {
41 match self {
42 Either::Left(l) => Some(l),
43 Either::Right(_) => None,
44 }
45 }
46
47 #[inline]
48 pub fn right(self) -> Option<B> {
50 match self {
51 Either::Left(_) => None,
52 Either::Right(r) => Some(r),
53 }
54 }
55
56 #[inline]
57 pub fn as_ref(&self) -> Either<&A, &B> {
59 match *self {
60 Either::Left(ref inner) => Either::Left(inner),
61 Either::Right(ref inner) => Either::Right(inner),
62 }
63 }
64
65 #[inline]
66 pub fn as_mut(&mut self) -> Either<&mut A, &mut B> {
68 match *self {
69 Either::Left(ref mut inner) => Either::Left(inner),
70 Either::Right(ref mut inner) => Either::Right(inner),
71 }
72 }
73}
74
75impl<T> Either<T, T> {
76 #[inline]
77 pub fn into_inner(self) -> T {
79 match self {
80 Either::Left(x) => x,
81 Either::Right(x) => x,
82 }
83 }
84}
85
86impl<A, B> error::Error for Either<A, B>
88where
89 A: error::Error,
90 B: error::Error,
91{
92 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
93 match self {
94 Either::Left(a) => a.source(),
95 Either::Right(b) => b.source(),
96 }
97 }
98}
99
100impl<A, B> fmt::Display for Either<A, B>
101where
102 A: fmt::Display,
103 B: fmt::Display,
104{
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 match self {
107 Either::Left(a) => a.fmt(f),
108 Either::Right(b) => b.fmt(f),
109 }
110 }
111}
112
113impl<A, B> Future for Either<A, B>
114where
115 A: Future,
116 B: Future<Output = A::Output>,
117{
118 type Output = A::Output;
119
120 #[inline]
121 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
122 match self.project() {
123 Either::Left(x) => x.poll(cx),
124 Either::Right(x) => x.poll(cx),
125 }
126 }
127}
128
129#[cfg(test)]
130mod test {
131 use super::*;
132
133 #[test]
134 #[allow(clippy::unit_cmp)]
135 fn either() {
136 let mut e = Either::<(), ()>::Left(());
137 assert!(e.is_left());
138 assert!(!e.is_right());
139 assert!(e.left().is_some());
140 assert!(e.right().is_none());
141 e.as_ref();
142 e.as_mut();
143
144 let mut e = Either::<(), ()>::Right(());
145 assert!(!e.is_left());
146 assert!(e.is_right());
147 assert!(e.left().is_none());
148 assert!(e.right().is_some());
149 e.as_ref();
150 e.as_mut();
151
152 assert_eq!(Either::<(), ()>::Left(()).into_inner(), ());
153 assert_eq!(Either::<(), ()>::Right(()).into_inner(), ());
154
155 assert_eq!(
156 format!("{}", Either::<_, &'static str>::Left("test")),
157 "test"
158 );
159 assert_eq!(
160 format!("{}", Either::<&'static str, _>::Right("test")),
161 "test"
162 );
163 }
164}