• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::pin::Pin;
2 use core::task::{Context, Poll};
3 use futures_core::future::{FusedFuture, Future};
4 use futures_core::stream::{FusedStream, Stream};
5 #[cfg(feature = "sink")]
6 use futures_sink::Sink;
7 
8 /// Combines two different futures, streams, or sinks having the same associated types into a single
9 /// type.
10 #[derive(Debug, Clone)]
11 pub enum Either<A, B> {
12     /// First branch of the type
13     Left(/* #[pin] */ A),
14     /// Second branch of the type
15     Right(/* #[pin] */ B),
16 }
17 
18 impl<A, B> Either<A, B> {
project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>>19     fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
20         unsafe {
21             match self.get_unchecked_mut() {
22                 Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
23                 Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
24             }
25         }
26     }
27 }
28 
29 impl<A, B, T> Either<(T, A), (T, B)> {
30     /// Factor out a homogeneous type from an either of pairs.
31     ///
32     /// Here, the homogeneous type is the first element of the pairs.
factor_first(self) -> (T, Either<A, B>)33     pub fn factor_first(self) -> (T, Either<A, B>) {
34         match self {
35             Either::Left((x, a)) => (x, Either::Left(a)),
36             Either::Right((x, b)) => (x, Either::Right(b)),
37         }
38     }
39 }
40 
41 impl<A, B, T> Either<(A, T), (B, T)> {
42     /// Factor out a homogeneous type from an either of pairs.
43     ///
44     /// Here, the homogeneous type is the second element of the pairs.
factor_second(self) -> (Either<A, B>, T)45     pub fn factor_second(self) -> (Either<A, B>, T) {
46         match self {
47             Either::Left((a, x)) => (Either::Left(a), x),
48             Either::Right((b, x)) => (Either::Right(b), x),
49         }
50     }
51 }
52 
53 impl<T> Either<T, T> {
54     /// Extract the value of an either over two equivalent types.
into_inner(self) -> T55     pub fn into_inner(self) -> T {
56         match self {
57             Either::Left(x) => x,
58             Either::Right(x) => x,
59         }
60     }
61 }
62 
63 impl<A, B> Future for Either<A, B>
64 where
65     A: Future,
66     B: Future<Output = A::Output>,
67 {
68     type Output = A::Output;
69 
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>70     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
71         match self.project() {
72             Either::Left(x) => x.poll(cx),
73             Either::Right(x) => x.poll(cx),
74         }
75     }
76 }
77 
78 impl<A, B> FusedFuture for Either<A, B>
79 where
80     A: FusedFuture,
81     B: FusedFuture<Output = A::Output>,
82 {
is_terminated(&self) -> bool83     fn is_terminated(&self) -> bool {
84         match self {
85             Either::Left(x) => x.is_terminated(),
86             Either::Right(x) => x.is_terminated(),
87         }
88     }
89 }
90 
91 impl<A, B> Stream for Either<A, B>
92 where
93     A: Stream,
94     B: Stream<Item = A::Item>,
95 {
96     type Item = A::Item;
97 
poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>98     fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
99         match self.project() {
100             Either::Left(x) => x.poll_next(cx),
101             Either::Right(x) => x.poll_next(cx),
102         }
103     }
104 
size_hint(&self) -> (usize, Option<usize>)105     fn size_hint(&self) -> (usize, Option<usize>) {
106         match self {
107             Either::Left(x) => x.size_hint(),
108             Either::Right(x) => x.size_hint(),
109         }
110     }
111 }
112 
113 impl<A, B> FusedStream for Either<A, B>
114 where
115     A: FusedStream,
116     B: FusedStream<Item = A::Item>,
117 {
is_terminated(&self) -> bool118     fn is_terminated(&self) -> bool {
119         match self {
120             Either::Left(x) => x.is_terminated(),
121             Either::Right(x) => x.is_terminated(),
122         }
123     }
124 }
125 
126 #[cfg(feature = "sink")]
127 impl<A, B, Item> Sink<Item> for Either<A, B>
128 where
129     A: Sink<Item>,
130     B: Sink<Item, Error = A::Error>,
131 {
132     type Error = A::Error;
133 
poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>134     fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
135         match self.project() {
136             Either::Left(x) => x.poll_ready(cx),
137             Either::Right(x) => x.poll_ready(cx),
138         }
139     }
140 
start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error>141     fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
142         match self.project() {
143             Either::Left(x) => x.start_send(item),
144             Either::Right(x) => x.start_send(item),
145         }
146     }
147 
poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>148     fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
149         match self.project() {
150             Either::Left(x) => x.poll_flush(cx),
151             Either::Right(x) => x.poll_flush(cx),
152         }
153     }
154 
poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>155     fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
156         match self.project() {
157             Either::Left(x) => x.poll_close(cx),
158             Either::Right(x) => x.poll_close(cx),
159         }
160     }
161 }
162 
163 #[cfg(feature = "io")]
164 #[cfg(feature = "std")]
165 mod if_std {
166     use super::*;
167 
168     use core::pin::Pin;
169     use core::task::{Context, Poll};
170     #[cfg(feature = "read-initializer")]
171     use futures_io::Initializer;
172     use futures_io::{
173         AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, Result, SeekFrom,
174     };
175 
176     impl<A, B> AsyncRead for Either<A, B>
177     where
178         A: AsyncRead,
179         B: AsyncRead,
180     {
181         #[cfg(feature = "read-initializer")]
initializer(&self) -> Initializer182         unsafe fn initializer(&self) -> Initializer {
183             match self {
184                 Either::Left(x) => x.initializer(),
185                 Either::Right(x) => x.initializer(),
186             }
187         }
188 
poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<Result<usize>>189         fn poll_read(
190             self: Pin<&mut Self>,
191             cx: &mut Context<'_>,
192             buf: &mut [u8],
193         ) -> Poll<Result<usize>> {
194             match self.project() {
195                 Either::Left(x) => x.poll_read(cx, buf),
196                 Either::Right(x) => x.poll_read(cx, buf),
197             }
198         }
199 
poll_read_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>], ) -> Poll<Result<usize>>200         fn poll_read_vectored(
201             self: Pin<&mut Self>,
202             cx: &mut Context<'_>,
203             bufs: &mut [IoSliceMut<'_>],
204         ) -> Poll<Result<usize>> {
205             match self.project() {
206                 Either::Left(x) => x.poll_read_vectored(cx, bufs),
207                 Either::Right(x) => x.poll_read_vectored(cx, bufs),
208             }
209         }
210     }
211 
212     impl<A, B> AsyncWrite for Either<A, B>
213     where
214         A: AsyncWrite,
215         B: AsyncWrite,
216     {
poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<Result<usize>>217         fn poll_write(
218             self: Pin<&mut Self>,
219             cx: &mut Context<'_>,
220             buf: &[u8],
221         ) -> Poll<Result<usize>> {
222             match self.project() {
223                 Either::Left(x) => x.poll_write(cx, buf),
224                 Either::Right(x) => x.poll_write(cx, buf),
225             }
226         }
227 
poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll<Result<usize>>228         fn poll_write_vectored(
229             self: Pin<&mut Self>,
230             cx: &mut Context<'_>,
231             bufs: &[IoSlice<'_>],
232         ) -> Poll<Result<usize>> {
233             match self.project() {
234                 Either::Left(x) => x.poll_write_vectored(cx, bufs),
235                 Either::Right(x) => x.poll_write_vectored(cx, bufs),
236             }
237         }
238 
poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>239         fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
240             match self.project() {
241                 Either::Left(x) => x.poll_flush(cx),
242                 Either::Right(x) => x.poll_flush(cx),
243             }
244         }
245 
poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>246         fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
247             match self.project() {
248                 Either::Left(x) => x.poll_close(cx),
249                 Either::Right(x) => x.poll_close(cx),
250             }
251         }
252     }
253 
254     impl<A, B> AsyncSeek for Either<A, B>
255     where
256         A: AsyncSeek,
257         B: AsyncSeek,
258     {
poll_seek( self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom, ) -> Poll<Result<u64>>259         fn poll_seek(
260             self: Pin<&mut Self>,
261             cx: &mut Context<'_>,
262             pos: SeekFrom,
263         ) -> Poll<Result<u64>> {
264             match self.project() {
265                 Either::Left(x) => x.poll_seek(cx, pos),
266                 Either::Right(x) => x.poll_seek(cx, pos),
267             }
268         }
269     }
270 
271     impl<A, B> AsyncBufRead for Either<A, B>
272     where
273         A: AsyncBufRead,
274         B: AsyncBufRead,
275     {
poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>>276         fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
277             match self.project() {
278                 Either::Left(x) => x.poll_fill_buf(cx),
279                 Either::Right(x) => x.poll_fill_buf(cx),
280             }
281         }
282 
consume(self: Pin<&mut Self>, amt: usize)283         fn consume(self: Pin<&mut Self>, amt: usize) {
284             match self.project() {
285                 Either::Left(x) => x.consume(amt),
286                 Either::Right(x) => x.consume(amt),
287             }
288         }
289     }
290 }
291