futures_util/future/
select.rs

1use futures_core::{Future, Poll, Async};
2use futures_core::task;
3
4use either::Either;
5
6/// Future for the `select` combinator, waiting for one of two differently-typed
7/// futures to complete.
8///
9/// This is created by the [`Future::select`] method.
10///
11/// [`Future::select`]: trait.Future.html#method.select
12#[must_use = "futures do nothing unless polled"]
13#[derive(Debug)]
14pub struct Select<A, B> {
15    inner: Option<(A, B)>,
16}
17
18pub fn new<A, B>(a: A, b: B) -> Select<A, B> {
19    Select { inner: Some((a, b)) }
20}
21
22impl<A, B> Future for Select<A, B> where A: Future, B: Future {
23    type Item = Either<(A::Item, B), (B::Item, A)>;
24    type Error = Either<(A::Error, B), (B::Error, A)>;
25
26    fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
27        let (mut a, mut b) = self.inner.take().expect("cannot poll Select twice");
28        match a.poll(cx) {
29            Err(e) => Err(Either::Left((e, b))),
30            Ok(Async::Ready(x)) => Ok(Async::Ready(Either::Left((x, b)))),
31            Ok(Async::Pending) => match b.poll(cx) {
32                Err(e) => Err(Either::Right((e, a))),
33                Ok(Async::Ready(x)) => Ok(Async::Ready(Either::Right((x, a)))),
34                Ok(Async::Pending) => {
35                    self.inner = Some((a, b));
36                    Ok(Async::Pending)
37                }
38            }
39        }
40    }
41}