1 use super::assert_future;
2 use crate::future::FutureExt;
3 use alloc::vec::Vec;
4 use core::iter::FromIterator;
5 use core::mem;
6 use core::pin::Pin;
7 use futures_core::future::Future;
8 use 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"]
13 pub struct SelectAll<Fut> {
14 inner: Vec<Fut>,
15 }
16
17 impl<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.
select_all<I>(iter: I) -> SelectAll<I::Item> where I: IntoIterator, I::Item: Future + Unpin,34 pub fn select_all<I>(iter: I) -> SelectAll<I::Item>
35 where
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
44 impl<Fut> SelectAll<Fut> {
45 /// Consumes this combinator, returning the underlying futures.
into_inner(self) -> Vec<Fut>46 pub fn into_inner(self) -> Vec<Fut> {
47 self.inner
48 }
49 }
50
51 impl<Fut: Future + Unpin> Future for SelectAll<Fut> {
52 type Output = (Fut::Output, usize, Vec<Fut>);
53
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>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
71 impl<Fut: Future + Unpin> FromIterator<Fut> for SelectAll<Fut> {
from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self72 fn from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self {
73 select_all(iter)
74 }
75 }
76