futures_util/future/
select_all.rs

1use super::assert_future;
2use crate::future::FutureExt;
3use alloc::vec::Vec;
4use core::iter::FromIterator;
5use core::mem;
6use core::pin::Pin;
7use futures_core::future::Future;
8use futures_core::task::{Context, Poll};
9
10/// Future for the [`select_all`] function.
11#[derive(Debug)]
12#[must_use = "futures do nothing unless you `.await` or poll them"]
13pub struct SelectAll<Fut> {
14    inner: Vec<Fut>,
15}
16
17impl<Fut: Unpin> Unpin for SelectAll<Fut> {}
18
19/// Creates a new future which will select over a list of futures.
20///
21/// The returned future will wait for any future within `iter` to be ready. Upon
22/// completion the item resolved will be returned, along with the index of the
23/// future that was ready and the list of all the remaining futures.
24///
25/// There are no guarantees provided on the order of the list with the remaining
26/// futures. They might be swapped around, reversed, or completely random.
27///
28/// This function is only available when the `std` or `alloc` feature of this
29/// library is activated, and it is activated by default.
30///
31/// # Panics
32///
33/// This function will panic if the iterator specified contains no items.
34pub fn select_all<I>(iter: I) -> SelectAll<I::Item>
35where
36    I: IntoIterator,
37    I::Item: Future + Unpin,
38{
39    let ret = SelectAll { inner: iter.into_iter().collect() };
40    assert!(!ret.inner.is_empty());
41    assert_future::<(<I::Item as Future>::Output, usize, Vec<I::Item>), _>(ret)
42}
43
44impl<Fut> SelectAll<Fut> {
45    /// Consumes this combinator, returning the underlying futures.
46    pub fn into_inner(self) -> Vec<Fut> {
47        self.inner
48    }
49}
50
51impl<Fut: Future + Unpin> Future for SelectAll<Fut> {
52    type Output = (Fut::Output, usize, Vec<Fut>);
53
54    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
55        let item = self.inner.iter_mut().enumerate().find_map(|(i, f)| match f.poll_unpin(cx) {
56            Poll::Pending => None,
57            Poll::Ready(e) => Some((i, e)),
58        });
59        match item {
60            Some((idx, res)) => {
61                #[allow(clippy::let_underscore_future)]
62                let _ = self.inner.swap_remove(idx);
63                let rest = mem::take(&mut self.inner);
64                Poll::Ready((res, idx, rest))
65            }
66            None => Poll::Pending,
67        }
68    }
69}
70
71impl<Fut: Future + Unpin> FromIterator<Fut> for SelectAll<Fut> {
72    fn from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self {
73        select_all(iter)
74    }
75}