use super::assert_future; use crate::future::FutureExt; use core::iter::FromIterator; use core::mem; use core::pin::Pin; use alloc::vec::Vec; use futures_core::future::Future; use futures_core::task::{Context, Poll}; /// Future for the [`select_all`] function. #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct SelectAll { inner: Vec, } impl Unpin for SelectAll {} /// Creates a new future which will select over a list of futures. /// /// The returned future will wait for any future within `iter` to be ready. Upon /// completion the item resolved will be returned, along with the index of the /// future that was ready and the list of all the remaining futures. /// /// There are no guarantees provided on the order of the list with the remaining /// futures. They might be swapped around, reversed, or completely random. /// /// This function is only available when the `std` or `alloc` feature of this /// library is activated, and it is activated by default. /// /// # Panics /// /// This function will panic if the iterator specified contains no items. pub fn select_all(iter: I) -> SelectAll where I: IntoIterator, I::Item: Future + Unpin, { let ret = SelectAll { inner: iter.into_iter().collect() }; assert!(!ret.inner.is_empty()); assert_future::<(::Output, usize, Vec), _>(ret) } impl Future for SelectAll { type Output = (Fut::Output, usize, Vec); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let item = self.inner.iter_mut().enumerate().find_map(|(i, f)| { match f.poll_unpin(cx) { Poll::Pending => None, Poll::Ready(e) => Some((i, e)), } }); match item { Some((idx, res)) => { let _ = self.inner.swap_remove(idx); let rest = mem::replace(&mut self.inner, Vec::new()); Poll::Ready((res, idx, rest)) } None => Poll::Pending, } } } impl FromIterator for SelectAll { fn from_iter>(iter: T) -> Self { select_all(iter) } }