From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../rust/futures-util/src/future/abortable.rs | 19 + third_party/rust/futures-util/src/future/either.rs | 317 +++++++++++ .../futures-util/src/future/future/catch_unwind.rs | 38 ++ .../rust/futures-util/src/future/future/flatten.rs | 153 +++++ .../rust/futures-util/src/future/future/fuse.rs | 93 +++ .../rust/futures-util/src/future/future/map.rs | 66 +++ .../rust/futures-util/src/future/future/mod.rs | 610 ++++++++++++++++++++ .../src/future/future/remote_handle.rs | 126 +++++ .../rust/futures-util/src/future/future/shared.rs | 413 ++++++++++++++ third_party/rust/futures-util/src/future/join.rs | 217 +++++++ .../rust/futures-util/src/future/join_all.rs | 166 ++++++ third_party/rust/futures-util/src/future/lazy.rs | 60 ++ .../rust/futures-util/src/future/maybe_done.rs | 104 ++++ third_party/rust/futures-util/src/future/mod.rs | 131 +++++ third_party/rust/futures-util/src/future/option.rs | 64 +++ .../rust/futures-util/src/future/pending.rs | 55 ++ .../rust/futures-util/src/future/poll_fn.rs | 58 ++ .../rust/futures-util/src/future/poll_immediate.rs | 126 +++++ third_party/rust/futures-util/src/future/ready.rs | 82 +++ third_party/rust/futures-util/src/future/select.rs | 125 +++++ .../rust/futures-util/src/future/select_all.rs | 75 +++ .../rust/futures-util/src/future/select_ok.rs | 85 +++ .../src/future/try_future/into_future.rs | 36 ++ .../rust/futures-util/src/future/try_future/mod.rs | 625 +++++++++++++++++++++ .../src/future/try_future/try_flatten.rs | 162 ++++++ .../src/future/try_future/try_flatten_err.rs | 62 ++ .../rust/futures-util/src/future/try_join.rs | 256 +++++++++ .../rust/futures-util/src/future/try_join_all.rs | 200 +++++++ .../rust/futures-util/src/future/try_maybe_done.rs | 92 +++ .../rust/futures-util/src/future/try_select.rs | 84 +++ 30 files changed, 4700 insertions(+) create mode 100644 third_party/rust/futures-util/src/future/abortable.rs create mode 100644 third_party/rust/futures-util/src/future/either.rs create mode 100644 third_party/rust/futures-util/src/future/future/catch_unwind.rs create mode 100644 third_party/rust/futures-util/src/future/future/flatten.rs create mode 100644 third_party/rust/futures-util/src/future/future/fuse.rs create mode 100644 third_party/rust/futures-util/src/future/future/map.rs create mode 100644 third_party/rust/futures-util/src/future/future/mod.rs create mode 100644 third_party/rust/futures-util/src/future/future/remote_handle.rs create mode 100644 third_party/rust/futures-util/src/future/future/shared.rs create mode 100644 third_party/rust/futures-util/src/future/join.rs create mode 100644 third_party/rust/futures-util/src/future/join_all.rs create mode 100644 third_party/rust/futures-util/src/future/lazy.rs create mode 100644 third_party/rust/futures-util/src/future/maybe_done.rs create mode 100644 third_party/rust/futures-util/src/future/mod.rs create mode 100644 third_party/rust/futures-util/src/future/option.rs create mode 100644 third_party/rust/futures-util/src/future/pending.rs create mode 100644 third_party/rust/futures-util/src/future/poll_fn.rs create mode 100644 third_party/rust/futures-util/src/future/poll_immediate.rs create mode 100644 third_party/rust/futures-util/src/future/ready.rs create mode 100644 third_party/rust/futures-util/src/future/select.rs create mode 100644 third_party/rust/futures-util/src/future/select_all.rs create mode 100644 third_party/rust/futures-util/src/future/select_ok.rs create mode 100644 third_party/rust/futures-util/src/future/try_future/into_future.rs create mode 100644 third_party/rust/futures-util/src/future/try_future/mod.rs create mode 100644 third_party/rust/futures-util/src/future/try_future/try_flatten.rs create mode 100644 third_party/rust/futures-util/src/future/try_future/try_flatten_err.rs create mode 100644 third_party/rust/futures-util/src/future/try_join.rs create mode 100644 third_party/rust/futures-util/src/future/try_join_all.rs create mode 100644 third_party/rust/futures-util/src/future/try_maybe_done.rs create mode 100644 third_party/rust/futures-util/src/future/try_select.rs (limited to 'third_party/rust/futures-util/src/future') diff --git a/third_party/rust/futures-util/src/future/abortable.rs b/third_party/rust/futures-util/src/future/abortable.rs new file mode 100644 index 0000000000..d017ab7340 --- /dev/null +++ b/third_party/rust/futures-util/src/future/abortable.rs @@ -0,0 +1,19 @@ +use super::assert_future; +use crate::future::{AbortHandle, Abortable, Aborted}; +use futures_core::future::Future; + +/// Creates a new `Abortable` future and an `AbortHandle` which can be used to stop it. +/// +/// This function is a convenient (but less flexible) alternative to calling +/// `AbortHandle::new` and `Abortable::new` manually. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +pub fn abortable(future: Fut) -> (Abortable, AbortHandle) +where + Fut: Future, +{ + let (handle, reg) = AbortHandle::new_pair(); + let abortable = assert_future::, _>(Abortable::new(future, reg)); + (abortable, handle) +} diff --git a/third_party/rust/futures-util/src/future/either.rs b/third_party/rust/futures-util/src/future/either.rs new file mode 100644 index 0000000000..27e5064dfb --- /dev/null +++ b/third_party/rust/futures-util/src/future/either.rs @@ -0,0 +1,317 @@ +use core::pin::Pin; +use core::task::{Context, Poll}; +use futures_core::future::{FusedFuture, Future}; +use futures_core::stream::{FusedStream, Stream}; +#[cfg(feature = "sink")] +use futures_sink::Sink; + +/// Combines two different futures, streams, or sinks having the same associated types into a single type. +/// +/// This is useful when conditionally choosing between two distinct future types: +/// +/// ```rust +/// use futures::future::Either; +/// +/// # futures::executor::block_on(async { +/// let cond = true; +/// +/// let fut = if cond { +/// Either::Left(async move { 12 }) +/// } else { +/// Either::Right(async move { 44 }) +/// }; +/// +/// assert_eq!(fut.await, 12); +/// # }) +/// ``` +#[derive(Debug, Clone)] +pub enum Either { + /// First branch of the type + Left(/* #[pin] */ A), + /// Second branch of the type + Right(/* #[pin] */ B), +} + +impl Either { + /// Convert `Pin<&Either>` to `Either, Pin<&B>>`, + /// pinned projections of the inner variants. + pub fn as_pin_ref(self: Pin<&Self>) -> Either, Pin<&B>> { + // SAFETY: We can use `new_unchecked` because the `inner` parts are + // guaranteed to be pinned, as they come from `self` which is pinned. + unsafe { + match *Pin::get_ref(self) { + Either::Left(ref inner) => Either::Left(Pin::new_unchecked(inner)), + Either::Right(ref inner) => Either::Right(Pin::new_unchecked(inner)), + } + } + } + + /// Convert `Pin<&mut Either>` to `Either, Pin<&mut B>>`, + /// pinned projections of the inner variants. + pub fn as_pin_mut(self: Pin<&mut Self>) -> Either, Pin<&mut B>> { + // SAFETY: `get_unchecked_mut` is fine because we don't move anything. + // We can use `new_unchecked` because the `inner` parts are guaranteed + // to be pinned, as they come from `self` which is pinned, and we never + // offer an unpinned `&mut A` or `&mut B` through `Pin<&mut Self>`. We + // also don't have an implementation of `Drop`, nor manual `Unpin`. + unsafe { + match *Pin::get_unchecked_mut(self) { + Either::Left(ref mut inner) => Either::Left(Pin::new_unchecked(inner)), + Either::Right(ref mut inner) => Either::Right(Pin::new_unchecked(inner)), + } + } + } +} + +impl Either<(T, A), (T, B)> { + /// Factor out a homogeneous type from an either of pairs. + /// + /// Here, the homogeneous type is the first element of the pairs. + pub fn factor_first(self) -> (T, Either) { + match self { + Either::Left((x, a)) => (x, Either::Left(a)), + Either::Right((x, b)) => (x, Either::Right(b)), + } + } +} + +impl Either<(A, T), (B, T)> { + /// Factor out a homogeneous type from an either of pairs. + /// + /// Here, the homogeneous type is the second element of the pairs. + pub fn factor_second(self) -> (Either, T) { + match self { + Either::Left((a, x)) => (Either::Left(a), x), + Either::Right((b, x)) => (Either::Right(b), x), + } + } +} + +impl Either { + /// Extract the value of an either over two equivalent types. + pub fn into_inner(self) -> T { + match self { + Either::Left(x) => x, + Either::Right(x) => x, + } + } +} + +impl Future for Either +where + A: Future, + B: Future, +{ + type Output = A::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_pin_mut() { + Either::Left(x) => x.poll(cx), + Either::Right(x) => x.poll(cx), + } + } +} + +impl FusedFuture for Either +where + A: FusedFuture, + B: FusedFuture, +{ + fn is_terminated(&self) -> bool { + match self { + Either::Left(x) => x.is_terminated(), + Either::Right(x) => x.is_terminated(), + } + } +} + +impl Stream for Either +where + A: Stream, + B: Stream, +{ + type Item = A::Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_next(cx), + Either::Right(x) => x.poll_next(cx), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + Either::Left(x) => x.size_hint(), + Either::Right(x) => x.size_hint(), + } + } +} + +impl FusedStream for Either +where + A: FusedStream, + B: FusedStream, +{ + fn is_terminated(&self) -> bool { + match self { + Either::Left(x) => x.is_terminated(), + Either::Right(x) => x.is_terminated(), + } + } +} + +#[cfg(feature = "sink")] +impl Sink for Either +where + A: Sink, + B: Sink, +{ + type Error = A::Error; + + fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_ready(cx), + Either::Right(x) => x.poll_ready(cx), + } + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + match self.as_pin_mut() { + Either::Left(x) => x.start_send(item), + Either::Right(x) => x.start_send(item), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_flush(cx), + Either::Right(x) => x.poll_flush(cx), + } + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_close(cx), + Either::Right(x) => x.poll_close(cx), + } + } +} + +#[cfg(feature = "io")] +#[cfg(feature = "std")] +mod if_std { + use super::*; + + use core::pin::Pin; + use core::task::{Context, Poll}; + use futures_io::{ + AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, Result, SeekFrom, + }; + + impl AsyncRead for Either + where + A: AsyncRead, + B: AsyncRead, + { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_read(cx, buf), + Either::Right(x) => x.poll_read(cx, buf), + } + } + + fn poll_read_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &mut [IoSliceMut<'_>], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_read_vectored(cx, bufs), + Either::Right(x) => x.poll_read_vectored(cx, bufs), + } + } + } + + impl AsyncWrite for Either + where + A: AsyncWrite, + B: AsyncWrite, + { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_write(cx, buf), + Either::Right(x) => x.poll_write(cx, buf), + } + } + + fn poll_write_vectored( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + bufs: &[IoSlice<'_>], + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_write_vectored(cx, bufs), + Either::Right(x) => x.poll_write_vectored(cx, bufs), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_flush(cx), + Either::Right(x) => x.poll_flush(cx), + } + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_close(cx), + Either::Right(x) => x.poll_close(cx), + } + } + } + + impl AsyncSeek for Either + where + A: AsyncSeek, + B: AsyncSeek, + { + fn poll_seek( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + pos: SeekFrom, + ) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_seek(cx, pos), + Either::Right(x) => x.poll_seek(cx, pos), + } + } + } + + impl AsyncBufRead for Either + where + A: AsyncBufRead, + B: AsyncBufRead, + { + fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_pin_mut() { + Either::Left(x) => x.poll_fill_buf(cx), + Either::Right(x) => x.poll_fill_buf(cx), + } + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + match self.as_pin_mut() { + Either::Left(x) => x.consume(amt), + Either::Right(x) => x.consume(amt), + } + } + } +} diff --git a/third_party/rust/futures-util/src/future/future/catch_unwind.rs b/third_party/rust/futures-util/src/future/future/catch_unwind.rs new file mode 100644 index 0000000000..0e09d6eeb0 --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/catch_unwind.rs @@ -0,0 +1,38 @@ +use core::any::Any; +use core::pin::Pin; +use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe}; + +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`catch_unwind`](super::FutureExt::catch_unwind) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct CatchUnwind { + #[pin] + future: Fut, + } +} + +impl CatchUnwind +where + Fut: Future + UnwindSafe, +{ + pub(super) fn new(future: Fut) -> Self { + Self { future } + } +} + +impl Future for CatchUnwind +where + Fut: Future + UnwindSafe, +{ + type Output = Result>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let f = self.project().future; + catch_unwind(AssertUnwindSafe(|| f.poll(cx)))?.map(Ok) + } +} diff --git a/third_party/rust/futures-util/src/future/future/flatten.rs b/third_party/rust/futures-util/src/future/future/flatten.rs new file mode 100644 index 0000000000..bd767af344 --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/flatten.rs @@ -0,0 +1,153 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + #[project = FlattenProj] + #[derive(Debug)] + pub enum Flatten { + First { #[pin] f: Fut1 }, + Second { #[pin] f: Fut2 }, + Empty, + } +} + +impl Flatten { + pub(crate) fn new(future: Fut1) -> Self { + Self::First { f: future } + } +} + +impl FusedFuture for Flatten +where + Fut: Future, + Fut::Output: Future, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Future for Flatten +where + Fut: Future, + Fut::Output: Future, +{ + type Output = ::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(loop { + match self.as_mut().project() { + FlattenProj::First { f } => { + let f = ready!(f.poll(cx)); + self.set(Self::Second { f }); + } + FlattenProj::Second { f } => { + let output = ready!(f.poll(cx)); + self.set(Self::Empty); + break output; + } + FlattenProj::Empty => panic!("Flatten polled after completion"), + } + }) + } +} + +impl FusedStream for Flatten +where + Fut: Future, + Fut::Output: Stream, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Stream for Flatten +where + Fut: Future, + Fut::Output: Stream, +{ + type Item = ::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + FlattenProj::First { f } => { + let f = ready!(f.poll(cx)); + self.set(Self::Second { f }); + } + FlattenProj::Second { f } => { + let output = ready!(f.poll_next(cx)); + if output.is_none() { + self.set(Self::Empty); + } + break output; + } + FlattenProj::Empty => break None, + } + }) + } +} + +#[cfg(feature = "sink")] +impl Sink for Flatten +where + Fut: Future, + Fut::Output: Sink, +{ + type Error = >::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + FlattenProj::First { f } => { + let f = ready!(f.poll(cx)); + self.set(Self::Second { f }); + } + FlattenProj::Second { f } => { + break ready!(f.poll_ready(cx)); + } + FlattenProj::Empty => panic!("poll_ready called after eof"), + } + }) + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + match self.project() { + FlattenProj::First { .. } => panic!("poll_ready not called first"), + FlattenProj::Second { f } => f.start_send(item), + FlattenProj::Empty => panic!("start_send called after eof"), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.project() { + FlattenProj::First { .. } => Poll::Ready(Ok(())), + FlattenProj::Second { f } => f.poll_flush(cx), + FlattenProj::Empty => panic!("poll_flush called after eof"), + } + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let res = match self.as_mut().project() { + FlattenProj::Second { f } => f.poll_close(cx), + _ => Poll::Ready(Ok(())), + }; + if res.is_ready() { + self.set(Self::Empty); + } + res + } +} diff --git a/third_party/rust/futures-util/src/future/future/fuse.rs b/third_party/rust/futures-util/src/future/future/fuse.rs new file mode 100644 index 0000000000..597aec1a40 --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/fuse.rs @@ -0,0 +1,93 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`fuse`](super::FutureExt::fuse) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct Fuse { + #[pin] + inner: Option, + } +} + +impl Fuse { + pub(super) fn new(f: Fut) -> Self { + Self { inner: Some(f) } + } +} + +impl Fuse { + /// Creates a new `Fuse`-wrapped future which is already terminated. + /// + /// This can be useful in combination with looping and the `select!` + /// macro, which bypasses terminated futures. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::channel::mpsc; + /// use futures::future::{Fuse, FusedFuture, FutureExt}; + /// use futures::select; + /// use futures::stream::StreamExt; + /// use futures::pin_mut; + /// + /// let (sender, mut stream) = mpsc::unbounded(); + /// + /// // Send a few messages into the stream + /// sender.unbounded_send(()).unwrap(); + /// sender.unbounded_send(()).unwrap(); + /// drop(sender); + /// + /// // Use `Fuse::terminated()` to create an already-terminated future + /// // which may be instantiated later. + /// let foo_printer = Fuse::terminated(); + /// pin_mut!(foo_printer); + /// + /// loop { + /// select! { + /// _ = foo_printer => {}, + /// () = stream.select_next_some() => { + /// if !foo_printer.is_terminated() { + /// println!("Foo is already being printed!"); + /// } else { + /// foo_printer.set(async { + /// // do some other async operations + /// println!("Printing foo from `foo_printer` future"); + /// }.fuse()); + /// } + /// }, + /// complete => break, // `foo_printer` is terminated and the stream is done + /// } + /// } + /// # }); + /// ``` + pub fn terminated() -> Self { + Self { inner: None } + } +} + +impl FusedFuture for Fuse { + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +impl Future for Fuse { + type Output = Fut::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(match self.as_mut().project().inner.as_pin_mut() { + Some(fut) => { + let output = ready!(fut.poll(cx)); + self.project().inner.set(None); + output + } + None => return Poll::Pending, + }) + } +} diff --git a/third_party/rust/futures-util/src/future/future/map.rs b/third_party/rust/futures-util/src/future/future/map.rs new file mode 100644 index 0000000000..7471aba000 --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/map.rs @@ -0,0 +1,66 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +use crate::fns::FnOnce1; + +pin_project! { + /// Internal Map future + #[project = MapProj] + #[project_replace = MapProjReplace] + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub enum Map { + Incomplete { + #[pin] + future: Fut, + f: F, + }, + Complete, + } +} + +impl Map { + /// Creates a new Map. + pub(crate) fn new(future: Fut, f: F) -> Self { + Self::Incomplete { future, f } + } +} + +impl FusedFuture for Map +where + Fut: Future, + F: FnOnce1, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Incomplete { .. } => false, + Self::Complete => true, + } + } +} + +impl Future for Map +where + Fut: Future, + F: FnOnce1, +{ + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.as_mut().project() { + MapProj::Incomplete { future, .. } => { + let output = ready!(future.poll(cx)); + match self.project_replace(Map::Complete) { + MapProjReplace::Incomplete { f, .. } => Poll::Ready(f.call_once(output)), + MapProjReplace::Complete => unreachable!(), + } + } + MapProj::Complete => { + panic!("Map must not be polled after it returned `Poll::Ready`") + } + } + } +} diff --git a/third_party/rust/futures-util/src/future/future/mod.rs b/third_party/rust/futures-util/src/future/future/mod.rs new file mode 100644 index 0000000000..c11d108207 --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/mod.rs @@ -0,0 +1,610 @@ +//! Futures +//! +//! This module contains a number of functions for working with `Future`s, +//! including the `FutureExt` trait which adds methods to `Future` types. + +#[cfg(feature = "alloc")] +use alloc::boxed::Box; +use core::pin::Pin; + +use crate::fns::{inspect_fn, into_fn, ok_fn, InspectFn, IntoFn, OkFn}; +use crate::future::{assert_future, Either}; +use crate::never::Never; +use crate::stream::assert_stream; +#[cfg(feature = "alloc")] +use futures_core::future::{BoxFuture, LocalBoxFuture}; +use futures_core::{ + future::Future, + stream::Stream, + task::{Context, Poll}, +}; +use pin_utils::pin_mut; + +// Combinators + +mod flatten; +mod fuse; +mod map; + +delegate_all!( + /// Future for the [`flatten`](super::FutureExt::flatten) method. + Flatten( + flatten::Flatten::Output> + ): Debug + Future + FusedFuture + New[|x: F| flatten::Flatten::new(x)] + where F: Future +); + +delegate_all!( + /// Stream for the [`flatten_stream`](FutureExt::flatten_stream) method. + FlattenStream( + flatten::Flatten::Output> + ): Debug + Sink + Stream + FusedStream + New[|x: F| flatten::Flatten::new(x)] + where F: Future +); + +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use fuse::Fuse; + +delegate_all!( + /// Future for the [`map`](super::FutureExt::map) method. + Map( + map::Map + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| map::Map::new(x, f)] +); + +delegate_all!( + /// Stream for the [`into_stream`](FutureExt::into_stream) method. + IntoStream( + crate::stream::Once + ): Debug + Stream + FusedStream + New[|x: F| crate::stream::Once::new(x)] +); + +delegate_all!( + /// Future for the [`map_into`](FutureExt::map_into) combinator. + MapInto( + Map> + ): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, into_fn())] +); + +delegate_all!( + /// Future for the [`then`](FutureExt::then) method. + Then( + flatten::Flatten, Fut2> + ): Debug + Future + FusedFuture + New[|x: Fut1, y: F| flatten::Flatten::new(Map::new(x, y))] +); + +delegate_all!( + /// Future for the [`inspect`](FutureExt::inspect) method. + Inspect( + map::Map> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| map::Map::new(x, inspect_fn(f))] +); + +delegate_all!( + /// Future for the [`never_error`](super::FutureExt::never_error) combinator. + NeverError( + Map> + ): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, ok_fn())] +); + +delegate_all!( + /// Future for the [`unit_error`](super::FutureExt::unit_error) combinator. + UnitError( + Map> + ): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, ok_fn())] +); + +#[cfg(feature = "std")] +mod catch_unwind; +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::catch_unwind::CatchUnwind; + +#[cfg(feature = "channel")] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +#[cfg(feature = "std")] +mod remote_handle; +#[cfg(feature = "channel")] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::remote_handle::{Remote, RemoteHandle}; + +#[cfg(feature = "std")] +mod shared; +#[cfg(feature = "std")] +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::shared::{Shared, WeakShared}; + +impl FutureExt for T where T: Future {} + +/// An extension trait for `Future`s that provides a variety of convenient +/// adapters. +pub trait FutureExt: Future { + /// Map this future's output to a different type, returning a new future of + /// the resulting type. + /// + /// This function is similar to the `Option::map` or `Iterator::map` where + /// it will change the type of the underlying future. This is useful to + /// chain along a computation once a future has been resolved. + /// + /// Note that this function consumes the receiving future and returns a + /// wrapped version of it, similar to the existing `map` methods in the + /// standard library. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future = async { 1 }; + /// let new_future = future.map(|x| x + 3); + /// assert_eq!(new_future.await, 4); + /// # }); + /// ``` + fn map(self, f: F) -> Map + where + F: FnOnce(Self::Output) -> U, + Self: Sized, + { + assert_future::(Map::new(self, f)) + } + + /// Map this future's output to a different type, returning a new future of + /// the resulting type. + /// + /// This function is equivalent to calling `map(Into::into)` but allows naming + /// the return type. + fn map_into(self) -> MapInto + where + Self::Output: Into, + Self: Sized, + { + assert_future::(MapInto::new(self)) + } + + /// Chain on a computation for when a future finished, passing the result of + /// the future to the provided closure `f`. + /// + /// The returned value of the closure must implement the `Future` trait + /// and can represent some more work to be done before the composed future + /// is finished. + /// + /// The closure `f` is only run *after* successful completion of the `self` + /// future. + /// + /// Note that this function consumes the receiving future and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future_of_1 = async { 1 }; + /// let future_of_4 = future_of_1.then(|x| async move { x + 3 }); + /// assert_eq!(future_of_4.await, 4); + /// # }); + /// ``` + fn then(self, f: F) -> Then + where + F: FnOnce(Self::Output) -> Fut, + Fut: Future, + Self: Sized, + { + assert_future::(Then::new(self, f)) + } + + /// Wrap this future in an `Either` future, making it the left-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `right_future` method to write `if` + /// statements that evaluate to different futures in different branches. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let x = 6; + /// let future = if x < 10 { + /// async { true }.left_future() + /// } else { + /// async { false }.right_future() + /// }; + /// + /// assert_eq!(future.await, true); + /// # }); + /// ``` + fn left_future(self) -> Either + where + B: Future, + Self: Sized, + { + assert_future::(Either::Left(self)) + } + + /// Wrap this future in an `Either` future, making it the right-hand variant + /// of that `Either`. + /// + /// This can be used in combination with the `left_future` method to write `if` + /// statements that evaluate to different futures in different branches. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let x = 6; + /// let future = if x > 10 { + /// async { true }.left_future() + /// } else { + /// async { false }.right_future() + /// }; + /// + /// assert_eq!(future.await, false); + /// # }); + /// ``` + fn right_future(self) -> Either + where + A: Future, + Self: Sized, + { + assert_future::(Either::Right(self)) + } + + /// Convert this future into a single element stream. + /// + /// The returned stream contains single success if this future resolves to + /// success or single error if this future resolves into error. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::stream::StreamExt; + /// + /// let future = async { 17 }; + /// let stream = future.into_stream(); + /// let collected: Vec<_> = stream.collect().await; + /// assert_eq!(collected, vec![17]); + /// # }); + /// ``` + fn into_stream(self) -> IntoStream + where + Self: Sized, + { + assert_stream::(IntoStream::new(self)) + } + + /// Flatten the execution of this future when the output of this + /// future is itself another future. + /// + /// This can be useful when combining futures together to flatten the + /// computation out the final result. + /// + /// This method is roughly equivalent to `self.then(|x| x)`. + /// + /// Note that this function consumes the receiving future and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let nested_future = async { async { 1 } }; + /// let future = nested_future.flatten(); + /// assert_eq!(future.await, 1); + /// # }); + /// ``` + fn flatten(self) -> Flatten + where + Self::Output: Future, + Self: Sized, + { + let f = Flatten::new(self); + assert_future::<<::Output as Future>::Output, _>(f) + } + + /// Flatten the execution of this future when the successful result of this + /// future is a stream. + /// + /// This can be useful when stream initialization is deferred, and it is + /// convenient to work with that stream as if stream was available at the + /// call site. + /// + /// Note that this function consumes this future and returns a wrapped + /// version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::stream::{self, StreamExt}; + /// + /// let stream_items = vec![17, 18, 19]; + /// let future_of_a_stream = async { stream::iter(stream_items) }; + /// + /// let stream = future_of_a_stream.flatten_stream(); + /// let list: Vec<_> = stream.collect().await; + /// assert_eq!(list, vec![17, 18, 19]); + /// # }); + /// ``` + fn flatten_stream(self) -> FlattenStream + where + Self::Output: Stream, + Self: Sized, + { + assert_stream::<::Item, _>(FlattenStream::new(self)) + } + + /// Fuse a future such that `poll` will never again be called once it has + /// completed. This method can be used to turn any `Future` into a + /// `FusedFuture`. + /// + /// Normally, once a future has returned `Poll::Ready` from `poll`, + /// any further calls could exhibit bad behavior such as blocking + /// forever, panicking, never returning, etc. If it is known that `poll` + /// may be called too often then this method can be used to ensure that it + /// has defined semantics. + /// + /// If a `fuse`d future is `poll`ed after having returned `Poll::Ready` + /// previously, it will return `Poll::Pending`, from `poll` again (and will + /// continue to do so for all future calls to `poll`). + /// + /// This combinator will drop the underlying future as soon as it has been + /// completed to ensure resources are reclaimed as soon as possible. + fn fuse(self) -> Fuse + where + Self: Sized, + { + let f = Fuse::new(self); + assert_future::(f) + } + + /// Do something with the output of a future before passing it on. + /// + /// When using futures, you'll often chain several of them together. While + /// working on such code, you might want to check out what's happening at + /// various parts in the pipeline, without consuming the intermediate + /// value. To do that, insert a call to `inspect`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future = async { 1 }; + /// let new_future = future.inspect(|&x| println!("about to resolve: {}", x)); + /// assert_eq!(new_future.await, 1); + /// # }); + /// ``` + fn inspect(self, f: F) -> Inspect + where + F: FnOnce(&Self::Output), + Self: Sized, + { + assert_future::(Inspect::new(self, f)) + } + + /// Catches unwinding panics while polling the future. + /// + /// In general, panics within a future can propagate all the way out to the + /// task level. This combinator makes it possible to halt unwinding within + /// the future itself. It's most commonly used within task executors. It's + /// not recommended to use this for error handling. + /// + /// Note that this method requires the `UnwindSafe` bound from the standard + /// library. This isn't always applied automatically, and the standard + /// library provides an `AssertUnwindSafe` wrapper type to apply it + /// after-the fact. To assist using this method, the `Future` trait is also + /// implemented for `AssertUnwindSafe` where `F` implements `Future`. + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::{self, FutureExt, Ready}; + /// + /// let future = future::ready(2); + /// assert!(future.catch_unwind().await.is_ok()); + /// + /// let future = future::lazy(|_| -> Ready { + /// unimplemented!() + /// }); + /// assert!(future.catch_unwind().await.is_err()); + /// # }); + /// ``` + #[cfg(feature = "std")] + fn catch_unwind(self) -> CatchUnwind + where + Self: Sized + ::std::panic::UnwindSafe, + { + assert_future::>, _>(CatchUnwind::new( + self, + )) + } + + /// Create a cloneable handle to this future where all handles will resolve + /// to the same result. + /// + /// The `shared` combinator method provides a method to convert any future + /// into a cloneable future. It enables a future to be polled by multiple + /// threads. + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// + /// let future = async { 6 }; + /// let shared1 = future.shared(); + /// let shared2 = shared1.clone(); + /// + /// assert_eq!(6, shared1.await); + /// assert_eq!(6, shared2.await); + /// # }); + /// ``` + /// + /// ``` + /// // Note, unlike most examples this is written in the context of a + /// // synchronous function to better illustrate the cross-thread aspect of + /// // the `shared` combinator. + /// + /// # futures::executor::block_on(async { + /// use futures::future::FutureExt; + /// use futures::executor::block_on; + /// use std::thread; + /// + /// let future = async { 6 }; + /// let shared1 = future.shared(); + /// let shared2 = shared1.clone(); + /// let join_handle = thread::spawn(move || { + /// assert_eq!(6, block_on(shared2)); + /// }); + /// assert_eq!(6, shared1.await); + /// join_handle.join().unwrap(); + /// # }); + /// ``` + #[cfg(feature = "std")] + fn shared(self) -> Shared + where + Self: Sized, + Self::Output: Clone, + { + assert_future::(Shared::new(self)) + } + + /// Turn this future into a future that yields `()` on completion and sends + /// its output to another future on a separate task. + /// + /// This can be used with spawning executors to easily retrieve the result + /// of a future executing on a separate task or thread. + /// + /// This method is only available when the `std` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "channel")] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + #[cfg(feature = "std")] + fn remote_handle(self) -> (Remote, RemoteHandle) + where + Self: Sized, + { + let (wrapped, handle) = remote_handle::remote_handle(self); + (assert_future::<(), _>(wrapped), handle) + } + + /// Wrap the future in a Box, pinning it. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn boxed<'a>(self) -> BoxFuture<'a, Self::Output> + where + Self: Sized + Send + 'a, + { + assert_future::(Box::pin(self)) + } + + /// Wrap the future in a Box, pinning it. + /// + /// Similar to `boxed`, but without the `Send` requirement. + /// + /// This method is only available when the `std` or `alloc` feature of this + /// library is activated, and it is activated by default. + #[cfg(feature = "alloc")] + fn boxed_local<'a>(self) -> LocalBoxFuture<'a, Self::Output> + where + Self: Sized + 'a, + { + assert_future::(Box::pin(self)) + } + + /// Turns a [`Future`](Future) into a + /// [`TryFuture](futures_core::future::TryFuture). + fn unit_error(self) -> UnitError + where + Self: Sized, + { + assert_future::, _>(UnitError::new(self)) + } + + /// Turns a [`Future`](Future) into a + /// [`TryFuture](futures_core::future::TryFuture). + fn never_error(self) -> NeverError + where + Self: Sized, + { + assert_future::, _>(NeverError::new(self)) + } + + /// A convenience for calling `Future::poll` on `Unpin` future types. + fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll + where + Self: Unpin, + { + Pin::new(self).poll(cx) + } + + /// Evaluates and consumes the future, returning the resulting output if + /// the future is ready after the first call to `Future::poll`. + /// + /// If `poll` instead returns `Poll::Pending`, `None` is returned. + /// + /// This method is useful in cases where immediacy is more important than + /// waiting for a result. It is also convenient for quickly obtaining + /// the value of a future that is known to always resolve immediately. + /// + /// # Examples + /// + /// ``` + /// # use futures::prelude::*; + /// use futures::{future::ready, future::pending}; + /// let future_ready = ready("foobar"); + /// let future_pending = pending::<&'static str>(); + /// + /// assert_eq!(future_ready.now_or_never(), Some("foobar")); + /// assert_eq!(future_pending.now_or_never(), None); + /// ``` + /// + /// In cases where it is absolutely known that a future should always + /// resolve immediately and never return `Poll::Pending`, this method can + /// be combined with `expect()`: + /// + /// ``` + /// # use futures::{prelude::*, future::ready}; + /// let future_ready = ready("foobar"); + /// + /// assert_eq!(future_ready.now_or_never().expect("Future not ready"), "foobar"); + /// ``` + fn now_or_never(self) -> Option + where + Self: Sized, + { + let noop_waker = crate::task::noop_waker(); + let mut cx = Context::from_waker(&noop_waker); + + let this = self; + pin_mut!(this); + match this.poll(&mut cx) { + Poll::Ready(x) => Some(x), + _ => None, + } + } +} diff --git a/third_party/rust/futures-util/src/future/future/remote_handle.rs b/third_party/rust/futures-util/src/future/future/remote_handle.rs new file mode 100644 index 0000000000..1358902cab --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/remote_handle.rs @@ -0,0 +1,126 @@ +use { + crate::future::{CatchUnwind, FutureExt}, + futures_channel::oneshot::{self, Receiver, Sender}, + futures_core::{ + future::Future, + ready, + task::{Context, Poll}, + }, + pin_project_lite::pin_project, + std::{ + any::Any, + fmt, + panic::{self, AssertUnwindSafe}, + pin::Pin, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + thread, + }, +}; + +/// The handle to a remote future returned by +/// [`remote_handle`](crate::future::FutureExt::remote_handle). When you drop this, +/// the remote future will be woken up to be dropped by the executor. +/// +/// ## Unwind safety +/// +/// When the remote future panics, [Remote] will catch the unwind and transfer it to +/// the thread where `RemoteHandle` is being awaited. This is good for the common +/// case where [Remote] is spawned on a threadpool. It is unlikely that other code +/// in the executor working thread shares mutable data with the spawned future and we +/// preserve the executor from losing its working threads. +/// +/// If you run the future locally and send the handle of to be awaited elsewhere, you +/// must be careful with regard to unwind safety because the thread in which the future +/// is polled will keep running after the panic and the thread running the [RemoteHandle] +/// will unwind. +#[must_use = "dropping a remote handle cancels the underlying future"] +#[derive(Debug)] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +pub struct RemoteHandle { + rx: Receiver>, + keep_running: Arc, +} + +impl RemoteHandle { + /// Drops this handle *without* canceling the underlying future. + /// + /// This method can be used if you want to drop the handle, but let the + /// execution continue. + pub fn forget(self) { + self.keep_running.store(true, Ordering::SeqCst); + } +} + +impl Future for RemoteHandle { + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match ready!(self.rx.poll_unpin(cx)) { + Ok(Ok(output)) => Poll::Ready(output), + // the remote future panicked. + Ok(Err(e)) => panic::resume_unwind(e), + // The oneshot sender was dropped. + Err(e) => panic::resume_unwind(Box::new(e)), + } + } +} + +type SendMsg = Result<::Output, Box<(dyn Any + Send + 'static)>>; + +pin_project! { + /// A future which sends its output to the corresponding `RemoteHandle`. + /// Created by [`remote_handle`](crate::future::FutureExt::remote_handle). + #[must_use = "futures do nothing unless you `.await` or poll them"] + #[cfg_attr(docsrs, doc(cfg(feature = "channel")))] + pub struct Remote { + tx: Option>>, + keep_running: Arc, + #[pin] + future: CatchUnwind>, + } +} + +impl fmt::Debug for Remote { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Remote").field(&self.future).finish() + } +} + +impl Future for Remote { + type Output = (); + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + let this = self.project(); + + if this.tx.as_mut().unwrap().poll_canceled(cx).is_ready() + && !this.keep_running.load(Ordering::SeqCst) + { + // Cancelled, bail out + return Poll::Ready(()); + } + + let output = ready!(this.future.poll(cx)); + + // if the receiving end has gone away then that's ok, we just ignore the + // send error here. + drop(this.tx.take().unwrap().send(output)); + Poll::Ready(()) + } +} + +pub(super) fn remote_handle(future: Fut) -> (Remote, RemoteHandle) { + let (tx, rx) = oneshot::channel(); + let keep_running = Arc::new(AtomicBool::new(false)); + + // Unwind Safety: See the docs for RemoteHandle. + let wrapped = Remote { + future: AssertUnwindSafe(future).catch_unwind(), + tx: Some(tx), + keep_running: keep_running.clone(), + }; + + (wrapped, RemoteHandle { rx, keep_running }) +} diff --git a/third_party/rust/futures-util/src/future/future/shared.rs b/third_party/rust/futures-util/src/future/future/shared.rs new file mode 100644 index 0000000000..ecd1b426db --- /dev/null +++ b/third_party/rust/futures-util/src/future/future/shared.rs @@ -0,0 +1,413 @@ +use crate::task::{waker_ref, ArcWake}; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll, Waker}; +use slab::Slab; +use std::cell::UnsafeCell; +use std::fmt; +use std::hash::Hasher; +use std::pin::Pin; +use std::ptr; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::{Acquire, SeqCst}; +use std::sync::{Arc, Mutex, Weak}; + +/// Future for the [`shared`](super::FutureExt::shared) method. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Shared { + inner: Option>>, + waker_key: usize, +} + +struct Inner { + future_or_output: UnsafeCell>, + notifier: Arc, +} + +struct Notifier { + state: AtomicUsize, + wakers: Mutex>>>, +} + +/// A weak reference to a [`Shared`] that can be upgraded much like an `Arc`. +pub struct WeakShared(Weak>); + +impl Clone for WeakShared { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +// The future itself is polled behind the `Arc`, so it won't be moved +// when `Shared` is moved. +impl Unpin for Shared {} + +impl fmt::Debug for Shared { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Shared") + .field("inner", &self.inner) + .field("waker_key", &self.waker_key) + .finish() + } +} + +impl fmt::Debug for Inner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Inner").finish() + } +} + +impl fmt::Debug for WeakShared { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WeakShared").finish() + } +} + +enum FutureOrOutput { + Future(Fut), + Output(Fut::Output), +} + +unsafe impl Send for Inner +where + Fut: Future + Send, + Fut::Output: Send + Sync, +{ +} + +unsafe impl Sync for Inner +where + Fut: Future + Send, + Fut::Output: Send + Sync, +{ +} + +const IDLE: usize = 0; +const POLLING: usize = 1; +const COMPLETE: usize = 2; +const POISONED: usize = 3; + +const NULL_WAKER_KEY: usize = usize::max_value(); + +impl Shared { + pub(super) fn new(future: Fut) -> Self { + let inner = Inner { + future_or_output: UnsafeCell::new(FutureOrOutput::Future(future)), + notifier: Arc::new(Notifier { + state: AtomicUsize::new(IDLE), + wakers: Mutex::new(Some(Slab::new())), + }), + }; + + Self { inner: Some(Arc::new(inner)), waker_key: NULL_WAKER_KEY } + } +} + +impl Shared +where + Fut: Future, +{ + /// Returns [`Some`] containing a reference to this [`Shared`]'s output if + /// it has already been computed by a clone or [`None`] if it hasn't been + /// computed yet or this [`Shared`] already returned its output from + /// [`poll`](Future::poll). + pub fn peek(&self) -> Option<&Fut::Output> { + if let Some(inner) = self.inner.as_ref() { + match inner.notifier.state.load(SeqCst) { + COMPLETE => unsafe { return Some(inner.output()) }, + POISONED => panic!("inner future panicked during poll"), + _ => {} + } + } + None + } + + /// Creates a new [`WeakShared`] for this [`Shared`]. + /// + /// Returns [`None`] if it has already been polled to completion. + pub fn downgrade(&self) -> Option> { + if let Some(inner) = self.inner.as_ref() { + return Some(WeakShared(Arc::downgrade(inner))); + } + None + } + + /// Gets the number of strong pointers to this allocation. + /// + /// Returns [`None`] if it has already been polled to completion. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. Another thread + /// can change the strong count at any time, including potentially between calling this method + /// and acting on the result. + #[allow(clippy::unnecessary_safety_doc)] + pub fn strong_count(&self) -> Option { + self.inner.as_ref().map(|arc| Arc::strong_count(arc)) + } + + /// Gets the number of weak pointers to this allocation. + /// + /// Returns [`None`] if it has already been polled to completion. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. Another thread + /// can change the weak count at any time, including potentially between calling this method + /// and acting on the result. + #[allow(clippy::unnecessary_safety_doc)] + pub fn weak_count(&self) -> Option { + self.inner.as_ref().map(|arc| Arc::weak_count(arc)) + } + + /// Hashes the internal state of this `Shared` in a way that's compatible with `ptr_eq`. + pub fn ptr_hash(&self, state: &mut H) { + match self.inner.as_ref() { + Some(arc) => { + state.write_u8(1); + ptr::hash(Arc::as_ptr(arc), state); + } + None => { + state.write_u8(0); + } + } + } + + /// Returns `true` if the two `Shared`s point to the same future (in a vein similar to + /// `Arc::ptr_eq`). + /// + /// Returns `false` if either `Shared` has terminated. + pub fn ptr_eq(&self, rhs: &Self) -> bool { + let lhs = match self.inner.as_ref() { + Some(lhs) => lhs, + None => return false, + }; + let rhs = match rhs.inner.as_ref() { + Some(rhs) => rhs, + None => return false, + }; + Arc::ptr_eq(lhs, rhs) + } +} + +impl Inner +where + Fut: Future, +{ + /// Safety: callers must first ensure that `self.inner.state` + /// is `COMPLETE` + unsafe fn output(&self) -> &Fut::Output { + match &*self.future_or_output.get() { + FutureOrOutput::Output(ref item) => item, + FutureOrOutput::Future(_) => unreachable!(), + } + } +} + +impl Inner +where + Fut: Future, + Fut::Output: Clone, +{ + /// Registers the current task to receive a wakeup when we are awoken. + fn record_waker(&self, waker_key: &mut usize, cx: &mut Context<'_>) { + let mut wakers_guard = self.notifier.wakers.lock().unwrap(); + + let wakers = match wakers_guard.as_mut() { + Some(wakers) => wakers, + None => return, + }; + + let new_waker = cx.waker(); + + if *waker_key == NULL_WAKER_KEY { + *waker_key = wakers.insert(Some(new_waker.clone())); + } else { + match wakers[*waker_key] { + Some(ref old_waker) if new_waker.will_wake(old_waker) => {} + // Could use clone_from here, but Waker doesn't specialize it. + ref mut slot => *slot = Some(new_waker.clone()), + } + } + debug_assert!(*waker_key != NULL_WAKER_KEY); + } + + /// Safety: callers must first ensure that `inner.state` + /// is `COMPLETE` + unsafe fn take_or_clone_output(self: Arc) -> Fut::Output { + match Arc::try_unwrap(self) { + Ok(inner) => match inner.future_or_output.into_inner() { + FutureOrOutput::Output(item) => item, + FutureOrOutput::Future(_) => unreachable!(), + }, + Err(inner) => inner.output().clone(), + } + } +} + +impl FusedFuture for Shared +where + Fut: Future, + Fut::Output: Clone, +{ + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} + +impl Future for Shared +where + Fut: Future, + Fut::Output: Clone, +{ + type Output = Fut::Output; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = &mut *self; + + let inner = this.inner.take().expect("Shared future polled again after completion"); + + // Fast path for when the wrapped future has already completed + if inner.notifier.state.load(Acquire) == COMPLETE { + // Safety: We're in the COMPLETE state + return unsafe { Poll::Ready(inner.take_or_clone_output()) }; + } + + inner.record_waker(&mut this.waker_key, cx); + + match inner + .notifier + .state + .compare_exchange(IDLE, POLLING, SeqCst, SeqCst) + .unwrap_or_else(|x| x) + { + IDLE => { + // Lock acquired, fall through + } + POLLING => { + // Another task is currently polling, at this point we just want + // to ensure that the waker for this task is registered + this.inner = Some(inner); + return Poll::Pending; + } + COMPLETE => { + // Safety: We're in the COMPLETE state + return unsafe { Poll::Ready(inner.take_or_clone_output()) }; + } + POISONED => panic!("inner future panicked during poll"), + _ => unreachable!(), + } + + let waker = waker_ref(&inner.notifier); + let mut cx = Context::from_waker(&waker); + + struct Reset<'a> { + state: &'a AtomicUsize, + did_not_panic: bool, + } + + impl Drop for Reset<'_> { + fn drop(&mut self) { + if !self.did_not_panic { + self.state.store(POISONED, SeqCst); + } + } + } + + let mut reset = Reset { state: &inner.notifier.state, did_not_panic: false }; + + let output = { + let future = unsafe { + match &mut *inner.future_or_output.get() { + FutureOrOutput::Future(fut) => Pin::new_unchecked(fut), + _ => unreachable!(), + } + }; + + let poll_result = future.poll(&mut cx); + reset.did_not_panic = true; + + match poll_result { + Poll::Pending => { + if inner.notifier.state.compare_exchange(POLLING, IDLE, SeqCst, SeqCst).is_ok() + { + // Success + drop(reset); + this.inner = Some(inner); + return Poll::Pending; + } else { + unreachable!() + } + } + Poll::Ready(output) => output, + } + }; + + unsafe { + *inner.future_or_output.get() = FutureOrOutput::Output(output); + } + + inner.notifier.state.store(COMPLETE, SeqCst); + + // Wake all tasks and drop the slab + let mut wakers_guard = inner.notifier.wakers.lock().unwrap(); + let mut wakers = wakers_guard.take().unwrap(); + for waker in wakers.drain().flatten() { + waker.wake(); + } + + drop(reset); // Make borrow checker happy + drop(wakers_guard); + + // Safety: We're in the COMPLETE state + unsafe { Poll::Ready(inner.take_or_clone_output()) } + } +} + +impl Clone for Shared +where + Fut: Future, +{ + fn clone(&self) -> Self { + Self { inner: self.inner.clone(), waker_key: NULL_WAKER_KEY } + } +} + +impl Drop for Shared +where + Fut: Future, +{ + fn drop(&mut self) { + if self.waker_key != NULL_WAKER_KEY { + if let Some(ref inner) = self.inner { + if let Ok(mut wakers) = inner.notifier.wakers.lock() { + if let Some(wakers) = wakers.as_mut() { + wakers.remove(self.waker_key); + } + } + } + } + } +} + +impl ArcWake for Notifier { + fn wake_by_ref(arc_self: &Arc) { + let wakers = &mut *arc_self.wakers.lock().unwrap(); + if let Some(wakers) = wakers.as_mut() { + for (_key, opt_waker) in wakers { + if let Some(waker) = opt_waker.take() { + waker.wake(); + } + } + } + } +} + +impl WeakShared { + /// Attempts to upgrade this [`WeakShared`] into a [`Shared`]. + /// + /// Returns [`None`] if all clones of the [`Shared`] have been dropped or polled + /// to completion. + pub fn upgrade(&self) -> Option> { + Some(Shared { inner: Some(self.0.upgrade()?), waker_key: NULL_WAKER_KEY }) + } +} diff --git a/third_party/rust/futures-util/src/future/join.rs b/third_party/rust/futures-util/src/future/join.rs new file mode 100644 index 0000000000..740ffbc988 --- /dev/null +++ b/third_party/rust/futures-util/src/future/join.rs @@ -0,0 +1,217 @@ +#![allow(non_snake_case)] + +use super::assert_future; +use crate::future::{maybe_done, MaybeDone}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +macro_rules! generate { + ($( + $(#[$doc:meta])* + ($Join:ident, <$($Fut:ident),*>), + )*) => ($( + pin_project! { + $(#[$doc])* + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct $Join<$($Fut: Future),*> { + $(#[pin] $Fut: MaybeDone<$Fut>,)* + } + } + + impl<$($Fut),*> fmt::Debug for $Join<$($Fut),*> + where + $( + $Fut: Future + fmt::Debug, + $Fut::Output: fmt::Debug, + )* + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(stringify!($Join)) + $(.field(stringify!($Fut), &self.$Fut))* + .finish() + } + } + + impl<$($Fut: Future),*> $Join<$($Fut),*> { + fn new($($Fut: $Fut),*) -> Self { + Self { + $($Fut: maybe_done($Fut)),* + } + } + } + + impl<$($Fut: Future),*> Future for $Join<$($Fut),*> { + type Output = ($($Fut::Output),*); + + fn poll( + self: Pin<&mut Self>, cx: &mut Context<'_> + ) -> Poll { + let mut all_done = true; + let mut futures = self.project(); + $( + all_done &= futures.$Fut.as_mut().poll(cx).is_ready(); + )* + + if all_done { + Poll::Ready(($(futures.$Fut.take_output().unwrap()), *)) + } else { + Poll::Pending + } + } + } + + impl<$($Fut: FusedFuture),*> FusedFuture for $Join<$($Fut),*> { + fn is_terminated(&self) -> bool { + $( + self.$Fut.is_terminated() + ) && * + } + } + )*) +} + +generate! { + /// Future for the [`join`](join()) function. + (Join, ), + + /// Future for the [`join3`] function. + (Join3, ), + + /// Future for the [`join4`] function. + (Join4, ), + + /// Future for the [`join5`] function. + (Join5, ), +} + +/// Joins the result of two futures, waiting for them both to complete. +/// +/// This function will return a new future which awaits both futures to +/// complete. The returned future will finish with a tuple of both results. +/// +/// Note that this function consumes the passed futures and returns a +/// wrapped version of it. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let pair = future::join(a, b); +/// +/// assert_eq!(pair.await, (1, 2)); +/// # }); +/// ``` +pub fn join(future1: Fut1, future2: Fut2) -> Join +where + Fut1: Future, + Fut2: Future, +{ + let f = Join::new(future1, future2); + assert_future::<(Fut1::Output, Fut2::Output), _>(f) +} + +/// Same as [`join`](join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let c = async { 3 }; +/// let tuple = future::join3(a, b, c); +/// +/// assert_eq!(tuple.await, (1, 2, 3)); +/// # }); +/// ``` +pub fn join3( + future1: Fut1, + future2: Fut2, + future3: Fut3, +) -> Join3 +where + Fut1: Future, + Fut2: Future, + Fut3: Future, +{ + let f = Join3::new(future1, future2, future3); + assert_future::<(Fut1::Output, Fut2::Output, Fut3::Output), _>(f) +} + +/// Same as [`join`](join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let c = async { 3 }; +/// let d = async { 4 }; +/// let tuple = future::join4(a, b, c, d); +/// +/// assert_eq!(tuple.await, (1, 2, 3, 4)); +/// # }); +/// ``` +pub fn join4( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, +) -> Join4 +where + Fut1: Future, + Fut2: Future, + Fut3: Future, + Fut4: Future, +{ + let f = Join4::new(future1, future2, future3, future4); + assert_future::<(Fut1::Output, Fut2::Output, Fut3::Output, Fut4::Output), _>(f) +} + +/// Same as [`join`](join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = async { 1 }; +/// let b = async { 2 }; +/// let c = async { 3 }; +/// let d = async { 4 }; +/// let e = async { 5 }; +/// let tuple = future::join5(a, b, c, d, e); +/// +/// assert_eq!(tuple.await, (1, 2, 3, 4, 5)); +/// # }); +/// ``` +pub fn join5( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, + future5: Fut5, +) -> Join5 +where + Fut1: Future, + Fut2: Future, + Fut3: Future, + Fut4: Future, + Fut5: Future, +{ + let f = Join5::new(future1, future2, future3, future4, future5); + assert_future::<(Fut1::Output, Fut2::Output, Fut3::Output, Fut4::Output, Fut5::Output), _>(f) +} diff --git a/third_party/rust/futures-util/src/future/join_all.rs b/third_party/rust/futures-util/src/future/join_all.rs new file mode 100644 index 0000000000..7dc159ba07 --- /dev/null +++ b/third_party/rust/futures-util/src/future/join_all.rs @@ -0,0 +1,166 @@ +//! Definition of the `JoinAll` combinator, waiting for all of a list of futures +//! to finish. + +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::fmt; +use core::future::Future; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use core::task::{Context, Poll}; + +use super::{assert_future, MaybeDone}; + +#[cfg(not(futures_no_atomic_cas))] +use crate::stream::{Collect, FuturesOrdered, StreamExt}; + +pub(crate) fn iter_pin_mut(slice: Pin<&mut [T]>) -> impl Iterator> { + // Safety: `std` _could_ make this unsound if it were to decide Pin's + // invariants aren't required to transmit through slices. Otherwise this has + // the same safety as a normal field pin projection. + unsafe { slice.get_unchecked_mut() }.iter_mut().map(|t| unsafe { Pin::new_unchecked(t) }) +} + +#[must_use = "futures do nothing unless you `.await` or poll them"] +/// Future for the [`join_all`] function. +pub struct JoinAll +where + F: Future, +{ + kind: JoinAllKind, +} + +#[cfg(not(futures_no_atomic_cas))] +pub(crate) const SMALL: usize = 30; + +enum JoinAllKind +where + F: Future, +{ + Small { + elems: Pin]>>, + }, + #[cfg(not(futures_no_atomic_cas))] + Big { + fut: Collect, Vec>, + }, +} + +impl fmt::Debug for JoinAll +where + F: Future + fmt::Debug, + F::Output: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + JoinAllKind::Small { ref elems } => { + f.debug_struct("JoinAll").field("elems", elems).finish() + } + #[cfg(not(futures_no_atomic_cas))] + JoinAllKind::Big { ref fut, .. } => fmt::Debug::fmt(fut, f), + } + } +} + +/// Creates a future which represents a collection of the outputs of the futures +/// given. +/// +/// The returned future will drive execution for all of its underlying futures, +/// collecting the results into a destination `Vec` in the same order as they +/// were provided. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +/// +/// # See Also +/// +/// `join_all` will switch to the more powerful [`FuturesOrdered`] for performance +/// reasons if the number of futures is large. You may want to look into using it or +/// it's counterpart [`FuturesUnordered`][crate::stream::FuturesUnordered] directly. +/// +/// Some examples for additional functionality provided by these are: +/// +/// * Adding new futures to the set even after it has been started. +/// +/// * Only polling the specific futures that have been woken. In cases where +/// you have a lot of futures this will result in much more efficient polling. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future::join_all; +/// +/// async fn foo(i: u32) -> u32 { i } +/// +/// let futures = vec![foo(1), foo(2), foo(3)]; +/// +/// assert_eq!(join_all(futures).await, [1, 2, 3]); +/// # }); +/// ``` +pub fn join_all(iter: I) -> JoinAll +where + I: IntoIterator, + I::Item: Future, +{ + let iter = iter.into_iter(); + + #[cfg(futures_no_atomic_cas)] + { + let kind = + JoinAllKind::Small { elems: iter.map(MaybeDone::Future).collect::>().into() }; + + assert_future::::Output>, _>(JoinAll { kind }) + } + + #[cfg(not(futures_no_atomic_cas))] + { + let kind = match iter.size_hint().1 { + Some(max) if max <= SMALL => JoinAllKind::Small { + elems: iter.map(MaybeDone::Future).collect::>().into(), + }, + _ => JoinAllKind::Big { fut: iter.collect::>().collect() }, + }; + + assert_future::::Output>, _>(JoinAll { kind }) + } +} + +impl Future for JoinAll +where + F: Future, +{ + type Output = Vec; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match &mut self.kind { + JoinAllKind::Small { elems } => { + let mut all_done = true; + + for elem in iter_pin_mut(elems.as_mut()) { + if elem.poll(cx).is_pending() { + all_done = false; + } + } + + if all_done { + let mut elems = mem::replace(elems, Box::pin([])); + let result = + iter_pin_mut(elems.as_mut()).map(|e| e.take_output().unwrap()).collect(); + Poll::Ready(result) + } else { + Poll::Pending + } + } + #[cfg(not(futures_no_atomic_cas))] + JoinAllKind::Big { fut } => Pin::new(fut).poll(cx), + } + } +} + +impl FromIterator for JoinAll { + fn from_iter>(iter: T) -> Self { + join_all(iter) + } +} diff --git a/third_party/rust/futures-util/src/future/lazy.rs b/third_party/rust/futures-util/src/future/lazy.rs new file mode 100644 index 0000000000..e9a8cf2fa9 --- /dev/null +++ b/third_party/rust/futures-util/src/future/lazy.rs @@ -0,0 +1,60 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`lazy`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Lazy { + f: Option, +} + +// safe because we never generate `Pin<&mut F>` +impl Unpin for Lazy {} + +/// Creates a new future that allows delayed execution of a closure. +/// +/// The provided closure is only run once the future is polled. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::lazy(|_| 1); +/// assert_eq!(a.await, 1); +/// +/// let b = future::lazy(|_| -> i32 { +/// panic!("oh no!") +/// }); +/// drop(b); // closure is never run +/// # }); +/// ``` +pub fn lazy(f: F) -> Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + assert_future::(Lazy { f: Some(f) }) +} + +impl FusedFuture for Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + fn is_terminated(&self) -> bool { + self.f.is_none() + } +} + +impl Future for Lazy +where + F: FnOnce(&mut Context<'_>) -> R, +{ + type Output = R; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready((self.f.take().expect("Lazy polled after completion"))(cx)) + } +} diff --git a/third_party/rust/futures-util/src/future/maybe_done.rs b/third_party/rust/futures-util/src/future/maybe_done.rs new file mode 100644 index 0000000000..26e6c27588 --- /dev/null +++ b/third_party/rust/futures-util/src/future/maybe_done.rs @@ -0,0 +1,104 @@ +//! Definition of the MaybeDone combinator + +use super::assert_future; +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; + +/// A future that may have completed. +/// +/// This is created by the [`maybe_done()`] function. +#[derive(Debug)] +pub enum MaybeDone { + /// A not-yet-completed future + Future(/* #[pin] */ Fut), + /// The output of the completed future + Done(Fut::Output), + /// The empty variant after the result of a [`MaybeDone`] has been + /// taken using the [`take_output`](MaybeDone::take_output) method. + Gone, +} + +impl Unpin for MaybeDone {} + +/// Wraps a future into a `MaybeDone` +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// use futures::pin_mut; +/// +/// let future = future::maybe_done(async { 5 }); +/// pin_mut!(future); +/// assert_eq!(future.as_mut().take_output(), None); +/// let () = future.as_mut().await; +/// assert_eq!(future.as_mut().take_output(), Some(5)); +/// assert_eq!(future.as_mut().take_output(), None); +/// # }); +/// ``` +pub fn maybe_done(future: Fut) -> MaybeDone { + assert_future::<(), _>(MaybeDone::Future(future)) +} + +impl MaybeDone { + /// Returns an [`Option`] containing a mutable reference to the output of the future. + /// The output of this method will be [`Some`] if and only if the inner + /// future has been completed and [`take_output`](MaybeDone::take_output) + /// has not yet been called. + #[inline] + pub fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> { + unsafe { + match self.get_unchecked_mut() { + MaybeDone::Done(res) => Some(res), + _ => None, + } + } + } + + /// Attempt to take the output of a `MaybeDone` without driving it + /// towards completion. + #[inline] + pub fn take_output(self: Pin<&mut Self>) -> Option { + match &*self { + Self::Done(_) => {} + Self::Future(_) | Self::Gone => return None, + } + unsafe { + match mem::replace(self.get_unchecked_mut(), Self::Gone) { + MaybeDone::Done(output) => Some(output), + _ => unreachable!(), + } + } + } +} + +impl FusedFuture for MaybeDone { + fn is_terminated(&self) -> bool { + match self { + Self::Future(_) => false, + Self::Done(_) | Self::Gone => true, + } + } +} + +impl Future for MaybeDone { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unsafe { + match self.as_mut().get_unchecked_mut() { + MaybeDone::Future(f) => { + let res = ready!(Pin::new_unchecked(f).poll(cx)); + self.set(Self::Done(res)); + } + MaybeDone::Done(_) => {} + MaybeDone::Gone => panic!("MaybeDone polled after value taken"), + } + } + Poll::Ready(()) + } +} diff --git a/third_party/rust/futures-util/src/future/mod.rs b/third_party/rust/futures-util/src/future/mod.rs new file mode 100644 index 0000000000..374e36512f --- /dev/null +++ b/third_party/rust/futures-util/src/future/mod.rs @@ -0,0 +1,131 @@ +//! Asynchronous values. +//! +//! This module contains: +//! +//! - The [`Future`] trait. +//! - The [`FutureExt`] and [`TryFutureExt`] trait, which provides adapters for +//! chaining and composing futures. +//! - Top-level future combinators like [`lazy`](lazy()) which creates a future +//! from a closure that defines its return value, and [`ready`](ready()), +//! which constructs a future with an immediate defined value. + +#[doc(no_inline)] +pub use core::future::Future; + +#[cfg(feature = "alloc")] +pub use futures_core::future::{BoxFuture, LocalBoxFuture}; +pub use futures_core::future::{FusedFuture, TryFuture}; +pub use futures_task::{FutureObj, LocalFutureObj, UnsafeFutureObj}; + +// Extension traits and combinators +#[allow(clippy::module_inception)] +mod future; +pub use self::future::{ + Flatten, Fuse, FutureExt, Inspect, IntoStream, Map, MapInto, NeverError, Then, UnitError, +}; + +#[deprecated(note = "This is now an alias for [Flatten](Flatten)")] +pub use self::future::FlattenStream; + +#[cfg(feature = "std")] +pub use self::future::CatchUnwind; + +#[cfg(feature = "channel")] +#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] +#[cfg(feature = "std")] +pub use self::future::{Remote, RemoteHandle}; + +#[cfg(feature = "std")] +pub use self::future::{Shared, WeakShared}; + +mod try_future; +pub use self::try_future::{ + AndThen, ErrInto, InspectErr, InspectOk, IntoFuture, MapErr, MapOk, MapOkOrElse, OkInto, + OrElse, TryFlatten, TryFlattenStream, TryFutureExt, UnwrapOrElse, +}; + +#[cfg(feature = "sink")] +#[cfg_attr(docsrs, doc(cfg(feature = "sink")))] +pub use self::try_future::FlattenSink; + +// Primitive futures + +mod lazy; +pub use self::lazy::{lazy, Lazy}; + +mod pending; +pub use self::pending::{pending, Pending}; + +mod maybe_done; +pub use self::maybe_done::{maybe_done, MaybeDone}; + +mod try_maybe_done; +pub use self::try_maybe_done::{try_maybe_done, TryMaybeDone}; + +mod option; +pub use self::option::OptionFuture; + +mod poll_fn; +pub use self::poll_fn::{poll_fn, PollFn}; + +mod poll_immediate; +pub use self::poll_immediate::{poll_immediate, PollImmediate}; + +mod ready; +pub use self::ready::{err, ok, ready, Ready}; + +mod join; +pub use self::join::{join, join3, join4, join5, Join, Join3, Join4, Join5}; + +#[cfg(feature = "alloc")] +mod join_all; +#[cfg(feature = "alloc")] +pub use self::join_all::{join_all, JoinAll}; + +mod select; +pub use self::select::{select, Select}; + +#[cfg(feature = "alloc")] +mod select_all; +#[cfg(feature = "alloc")] +pub use self::select_all::{select_all, SelectAll}; + +mod try_join; +pub use self::try_join::{ + try_join, try_join3, try_join4, try_join5, TryJoin, TryJoin3, TryJoin4, TryJoin5, +}; + +#[cfg(feature = "alloc")] +mod try_join_all; +#[cfg(feature = "alloc")] +pub use self::try_join_all::{try_join_all, TryJoinAll}; + +mod try_select; +pub use self::try_select::{try_select, TrySelect}; + +#[cfg(feature = "alloc")] +mod select_ok; +#[cfg(feature = "alloc")] +pub use self::select_ok::{select_ok, SelectOk}; + +mod either; +pub use self::either::Either; + +#[cfg(not(futures_no_atomic_cas))] +#[cfg(feature = "alloc")] +mod abortable; +#[cfg(not(futures_no_atomic_cas))] +#[cfg(feature = "alloc")] +pub use crate::abortable::{AbortHandle, AbortRegistration, Abortable, Aborted}; +#[cfg(not(futures_no_atomic_cas))] +#[cfg(feature = "alloc")] +pub use abortable::abortable; + +// Just a helper function to ensure the futures we're returning all have the +// right implementations. +pub(crate) fn assert_future(future: F) -> F +where + F: Future, +{ + future +} diff --git a/third_party/rust/futures-util/src/future/option.rs b/third_party/rust/futures-util/src/future/option.rs new file mode 100644 index 0000000000..0bc377758a --- /dev/null +++ b/third_party/rust/futures-util/src/future/option.rs @@ -0,0 +1,64 @@ +//! Definition of the `Option` (optional step) combinator + +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// A future representing a value which may or may not be present. + /// + /// Created by the [`From`] implementation for [`Option`](std::option::Option). + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::OptionFuture; + /// + /// let mut a: OptionFuture<_> = Some(async { 123 }).into(); + /// assert_eq!(a.await, Some(123)); + /// + /// a = None.into(); + /// assert_eq!(a.await, None); + /// # }); + /// ``` + #[derive(Debug, Clone)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct OptionFuture { + #[pin] + inner: Option, + } +} + +impl Default for OptionFuture { + fn default() -> Self { + Self { inner: None } + } +} + +impl Future for OptionFuture { + type Output = Option; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.project().inner.as_pin_mut() { + Some(x) => x.poll(cx).map(Some), + None => Poll::Ready(None), + } + } +} + +impl FusedFuture for OptionFuture { + fn is_terminated(&self) -> bool { + match &self.inner { + Some(x) => x.is_terminated(), + None => true, + } + } +} + +impl From> for OptionFuture { + fn from(option: Option) -> Self { + Self { inner: option } + } +} diff --git a/third_party/rust/futures-util/src/future/pending.rs b/third_party/rust/futures-util/src/future/pending.rs new file mode 100644 index 0000000000..b8e28686e1 --- /dev/null +++ b/third_party/rust/futures-util/src/future/pending.rs @@ -0,0 +1,55 @@ +use super::assert_future; +use core::marker; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`pending()`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Pending { + _data: marker::PhantomData, +} + +impl FusedFuture for Pending { + fn is_terminated(&self) -> bool { + true + } +} + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// The returned future will forever return [`Poll::Pending`]. +/// +/// # Examples +/// +/// ```ignore +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let future = future::pending(); +/// let () = future.await; +/// unreachable!(); +/// # }); +/// ``` +#[cfg_attr(docsrs, doc(alias = "never"))] +pub fn pending() -> Pending { + assert_future::(Pending { _data: marker::PhantomData }) +} + +impl Future for Pending { + type Output = T; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +impl Unpin for Pending {} + +impl Clone for Pending { + fn clone(&self) -> Self { + pending() + } +} diff --git a/third_party/rust/futures-util/src/future/poll_fn.rs b/third_party/rust/futures-util/src/future/poll_fn.rs new file mode 100644 index 0000000000..19311570b5 --- /dev/null +++ b/third_party/rust/futures-util/src/future/poll_fn.rs @@ -0,0 +1,58 @@ +//! Definition of the `PollFn` adapter combinator + +use super::assert_future; +use core::fmt; +use core::pin::Pin; +use futures_core::future::Future; +use futures_core::task::{Context, Poll}; + +/// Future for the [`poll_fn`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct PollFn { + f: F, +} + +impl Unpin for PollFn {} + +/// Creates a new future wrapping around a function returning [`Poll`]. +/// +/// Polling the returned future delegates to the wrapped function. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future::poll_fn; +/// use futures::task::{Context, Poll}; +/// +/// fn read_line(_cx: &mut Context<'_>) -> Poll { +/// Poll::Ready("Hello, World!".into()) +/// } +/// +/// let read_future = poll_fn(read_line); +/// assert_eq!(read_future.await, "Hello, World!".to_owned()); +/// # }); +/// ``` +pub fn poll_fn(f: F) -> PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + assert_future::(PollFn { f }) +} + +impl fmt::Debug for PollFn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("PollFn").finish() + } +} + +impl Future for PollFn +where + F: FnMut(&mut Context<'_>) -> Poll, +{ + type Output = T; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + (&mut self.f)(cx) + } +} diff --git a/third_party/rust/futures-util/src/future/poll_immediate.rs b/third_party/rust/futures-util/src/future/poll_immediate.rs new file mode 100644 index 0000000000..5ae555c73e --- /dev/null +++ b/third_party/rust/futures-util/src/future/poll_immediate.rs @@ -0,0 +1,126 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::task::{Context, Poll}; +use futures_core::{FusedFuture, Future, Stream}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`poll_immediate`](poll_immediate()) function. + /// + /// It will never return [Poll::Pending](core::task::Poll::Pending) + #[derive(Debug, Clone)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct PollImmediate { + #[pin] + future: Option + } +} + +impl Future for PollImmediate +where + F: Future, +{ + type Output = Option; + + #[inline] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + let inner = + this.future.as_mut().as_pin_mut().expect("PollImmediate polled after completion"); + match inner.poll(cx) { + Poll::Ready(t) => { + this.future.set(None); + Poll::Ready(Some(t)) + } + Poll::Pending => Poll::Ready(None), + } + } +} + +impl FusedFuture for PollImmediate { + fn is_terminated(&self) -> bool { + self.future.is_none() + } +} + +/// A [Stream](crate::stream::Stream) implementation that can be polled repeatedly until the future is done. +/// The stream will never return [Poll::Pending](core::task::Poll::Pending) +/// so polling it in a tight loop is worse than using a blocking synchronous function. +/// ``` +/// # futures::executor::block_on(async { +/// use futures::task::Poll; +/// use futures::{StreamExt, future, pin_mut}; +/// use future::FusedFuture; +/// +/// let f = async { 1_u32 }; +/// pin_mut!(f); +/// let mut r = future::poll_immediate(f); +/// assert_eq!(r.next().await, Some(Poll::Ready(1))); +/// +/// let f = async {futures::pending!(); 42_u8}; +/// pin_mut!(f); +/// let mut p = future::poll_immediate(f); +/// assert_eq!(p.next().await, Some(Poll::Pending)); +/// assert!(!p.is_terminated()); +/// assert_eq!(p.next().await, Some(Poll::Ready(42))); +/// assert!(p.is_terminated()); +/// assert_eq!(p.next().await, None); +/// # }); +/// ``` +impl Stream for PollImmediate +where + F: Future, +{ + type Item = Poll; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut this = self.project(); + match this.future.as_mut().as_pin_mut() { + // inner is gone, so we can signal that the stream is closed. + None => Poll::Ready(None), + Some(fut) => Poll::Ready(Some(fut.poll(cx).map(|t| { + this.future.set(None); + t + }))), + } + } +} + +/// Creates a future that is immediately ready with an Option of a value. +/// Specifically this means that [poll](core::future::Future::poll()) always returns [Poll::Ready](core::task::Poll::Ready). +/// +/// # Caution +/// +/// When consuming the future by this function, note the following: +/// +/// - This function does not guarantee that the future will run to completion, so it is generally incompatible with passing the non-cancellation-safe future by value. +/// - Even if the future is cancellation-safe, creating and dropping new futures frequently may lead to performance problems. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let r = future::poll_immediate(async { 1_u32 }); +/// assert_eq!(r.await, Some(1)); +/// +/// let p = future::poll_immediate(future::pending::()); +/// assert_eq!(p.await, None); +/// # }); +/// ``` +/// +/// ### Reusing a future +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::{future, pin_mut}; +/// let f = async {futures::pending!(); 42_u8}; +/// pin_mut!(f); +/// assert_eq!(None, future::poll_immediate(&mut f).await); +/// assert_eq!(42, f.await); +/// # }); +/// ``` +pub fn poll_immediate(f: F) -> PollImmediate { + assert_future::, PollImmediate>(PollImmediate { future: Some(f) }) +} diff --git a/third_party/rust/futures-util/src/future/ready.rs b/third_party/rust/futures-util/src/future/ready.rs new file mode 100644 index 0000000000..e3d791b3cf --- /dev/null +++ b/third_party/rust/futures-util/src/future/ready.rs @@ -0,0 +1,82 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`ready`](ready()) function. +#[derive(Debug, Clone)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct Ready(Option); + +impl Ready { + /// Unwraps the value from this immediately ready future. + #[inline] + pub fn into_inner(mut self) -> T { + self.0.take().unwrap() + } +} + +impl Unpin for Ready {} + +impl FusedFuture for Ready { + fn is_terminated(&self) -> bool { + self.0.is_none() + } +} + +impl Future for Ready { + type Output = T; + + #[inline] + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().expect("Ready polled after completion")) + } +} + +/// Creates a future that is immediately ready with a value. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(1); +/// assert_eq!(a.await, 1); +/// # }); +/// ``` +pub fn ready(t: T) -> Ready { + assert_future::(Ready(Some(t))) +} + +/// Create a future that is immediately ready with a success value. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ok::(1); +/// assert_eq!(a.await, Ok(1)); +/// # }); +/// ``` +pub fn ok(t: T) -> Ready> { + Ready(Some(Ok(t))) +} + +/// Create a future that is immediately ready with an error value. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::err::(1); +/// assert_eq!(a.await, Err(1)); +/// # }); +/// ``` +pub fn err(err: E) -> Ready> { + Ready(Some(Err(err))) +} diff --git a/third_party/rust/futures-util/src/future/select.rs b/third_party/rust/futures-util/src/future/select.rs new file mode 100644 index 0000000000..e693a30b00 --- /dev/null +++ b/third_party/rust/futures-util/src/future/select.rs @@ -0,0 +1,125 @@ +use super::assert_future; +use crate::future::{Either, FutureExt}; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`select()`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +pub struct Select { + inner: Option<(A, B)>, +} + +impl Unpin for Select {} + +/// Waits for either one of two differently-typed futures to complete. +/// +/// This function will return a new future which awaits for either one of both +/// futures to complete. The returned future will finish with both the value +/// resolved and a future representing the completion of the other work. +/// +/// Note that this function consumes the receiving futures and returns a +/// wrapped version of them. +/// +/// Also note that if both this and the second future have the same +/// output type you can use the `Either::factor_first` method to +/// conveniently extract out the value at the end. +/// +/// # Examples +/// +/// A simple example +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::{ +/// pin_mut, +/// future::Either, +/// future::self, +/// }; +/// +/// // These two futures have different types even though their outputs have the same type. +/// let future1 = async { +/// future::pending::<()>().await; // will never finish +/// 1 +/// }; +/// let future2 = async { +/// future::ready(2).await +/// }; +/// +/// // 'select' requires Future + Unpin bounds +/// pin_mut!(future1); +/// pin_mut!(future2); +/// +/// let value = match future::select(future1, future2).await { +/// Either::Left((value1, _)) => value1, // `value1` is resolved from `future1` +/// // `_` represents `future2` +/// Either::Right((value2, _)) => value2, // `value2` is resolved from `future2` +/// // `_` represents `future1` +/// }; +/// +/// assert!(value == 2); +/// # }); +/// ``` +/// +/// A more complex example +/// +/// ``` +/// use futures::future::{self, Either, Future, FutureExt}; +/// +/// // A poor-man's join implemented on top of select +/// +/// fn join(a: A, b: B) -> impl Future +/// where A: Future + Unpin, +/// B: Future + Unpin, +/// { +/// future::select(a, b).then(|either| { +/// match either { +/// Either::Left((x, b)) => b.map(move |y| (x, y)).left_future(), +/// Either::Right((y, a)) => a.map(move |x| (x, y)).right_future(), +/// } +/// }) +/// } +/// ``` +pub fn select(future1: A, future2: B) -> Select +where + A: Future + Unpin, + B: Future + Unpin, +{ + assert_future::, _>(Select { + inner: Some((future1, future2)), + }) +} + +impl Future for Select +where + A: Future + Unpin, + B: Future + Unpin, +{ + type Output = Either<(A::Output, B), (B::Output, A)>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let (mut a, mut b) = self.inner.take().expect("cannot poll Select twice"); + + if let Poll::Ready(val) = a.poll_unpin(cx) { + return Poll::Ready(Either::Left((val, b))); + } + + if let Poll::Ready(val) = b.poll_unpin(cx) { + return Poll::Ready(Either::Right((val, a))); + } + + self.inner = Some((a, b)); + Poll::Pending + } +} + +impl FusedFuture for Select +where + A: Future + Unpin, + B: Future + Unpin, +{ + fn is_terminated(&self) -> bool { + self.inner.is_none() + } +} diff --git a/third_party/rust/futures-util/src/future/select_all.rs b/third_party/rust/futures-util/src/future/select_all.rs new file mode 100644 index 0000000000..0a51d0da6c --- /dev/null +++ b/third_party/rust/futures-util/src/future/select_all.rs @@ -0,0 +1,75 @@ +use super::assert_future; +use crate::future::FutureExt; +use alloc::vec::Vec; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +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 SelectAll { + /// Consumes this combinator, returning the underlying futures. + pub fn into_inner(self) -> Vec { + self.inner + } +} + +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)) => { + #[allow(clippy::let_underscore_future)] + let _ = self.inner.swap_remove(idx); + let rest = mem::take(&mut self.inner); + Poll::Ready((res, idx, rest)) + } + None => Poll::Pending, + } + } +} + +impl FromIterator for SelectAll { + fn from_iter>(iter: T) -> Self { + select_all(iter) + } +} diff --git a/third_party/rust/futures-util/src/future/select_ok.rs b/third_party/rust/futures-util/src/future/select_ok.rs new file mode 100644 index 0000000000..5d5579930b --- /dev/null +++ b/third_party/rust/futures-util/src/future/select_ok.rs @@ -0,0 +1,85 @@ +use super::assert_future; +use crate::future::TryFutureExt; +use alloc::vec::Vec; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`select_ok`] function. +#[derive(Debug)] +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct SelectOk { + inner: Vec, +} + +impl Unpin for SelectOk {} + +/// Creates a new future which will select the first successful future over a list of futures. +/// +/// The returned future will wait for any future within `iter` to be ready and Ok. Unlike +/// `select_all`, this will only return the first successful completion, or the last +/// failure. This is useful in contexts where any success is desired and failures +/// are ignored, unless all the futures fail. +/// +/// 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_ok(iter: I) -> SelectOk +where + I: IntoIterator, + I::Item: TryFuture + Unpin, +{ + let ret = SelectOk { inner: iter.into_iter().collect() }; + assert!(!ret.inner.is_empty(), "iterator provided to select_ok was empty"); + assert_future::< + Result<(::Ok, Vec), ::Error>, + _, + >(ret) +} + +impl Future for SelectOk { + type Output = Result<(Fut::Ok, Vec), Fut::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // loop until we've either exhausted all errors, a success was hit, or nothing is ready + loop { + let item = + self.inner.iter_mut().enumerate().find_map(|(i, f)| match f.try_poll_unpin(cx) { + Poll::Pending => None, + Poll::Ready(e) => Some((i, e)), + }); + match item { + Some((idx, res)) => { + // always remove Ok or Err, if it's not the last Err continue looping + drop(self.inner.remove(idx)); + match res { + Ok(e) => { + let rest = mem::take(&mut self.inner); + return Poll::Ready(Ok((e, rest))); + } + Err(e) => { + if self.inner.is_empty() { + return Poll::Ready(Err(e)); + } + } + } + } + None => { + // based on the filter above, nothing is ready, return + return Poll::Pending; + } + } + } + } +} + +impl FromIterator for SelectOk { + fn from_iter>(iter: T) -> Self { + select_ok(iter) + } +} diff --git a/third_party/rust/futures-util/src/future/try_future/into_future.rs b/third_party/rust/futures-util/src/future/try_future/into_future.rs new file mode 100644 index 0000000000..9f093d0e2e --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_future/into_future.rs @@ -0,0 +1,36 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + /// Future for the [`into_future`](super::TryFutureExt::into_future) method. + #[derive(Debug)] + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct IntoFuture { + #[pin] + future: Fut, + } +} + +impl IntoFuture { + #[inline] + pub(crate) fn new(future: Fut) -> Self { + Self { future } + } +} + +impl FusedFuture for IntoFuture { + fn is_terminated(&self) -> bool { + self.future.is_terminated() + } +} + +impl Future for IntoFuture { + type Output = Result; + + #[inline] + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.project().future.try_poll(cx) + } +} diff --git a/third_party/rust/futures-util/src/future/try_future/mod.rs b/third_party/rust/futures-util/src/future/try_future/mod.rs new file mode 100644 index 0000000000..e5bc700714 --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_future/mod.rs @@ -0,0 +1,625 @@ +//! Futures +//! +//! This module contains a number of functions for working with `Future`s, +//! including the `FutureExt` trait which adds methods to `Future` types. + +#[cfg(feature = "compat")] +use crate::compat::Compat; +use core::pin::Pin; +use futures_core::{ + future::TryFuture, + stream::TryStream, + task::{Context, Poll}, +}; +#[cfg(feature = "sink")] +use futures_sink::Sink; + +use crate::fns::{ + inspect_err_fn, inspect_ok_fn, into_fn, map_err_fn, map_ok_fn, map_ok_or_else_fn, + unwrap_or_else_fn, InspectErrFn, InspectOkFn, IntoFn, MapErrFn, MapOkFn, MapOkOrElseFn, + UnwrapOrElseFn, +}; +use crate::future::{assert_future, Inspect, Map}; +use crate::stream::assert_stream; + +// Combinators +mod into_future; +mod try_flatten; +mod try_flatten_err; + +delegate_all!( + /// Future for the [`try_flatten`](TryFutureExt::try_flatten) method. + TryFlatten( + try_flatten::TryFlatten + ): Debug + Future + FusedFuture + New[|x: Fut1| try_flatten::TryFlatten::new(x)] +); + +delegate_all!( + /// Future for the [`try_flatten_err`](TryFutureExt::try_flatten_err) method. + TryFlattenErr( + try_flatten_err::TryFlattenErr + ): Debug + Future + FusedFuture + New[|x: Fut1| try_flatten_err::TryFlattenErr::new(x)] +); + +delegate_all!( + /// Future for the [`try_flatten_stream`](TryFutureExt::try_flatten_stream) method. + TryFlattenStream( + try_flatten::TryFlatten + ): Debug + Sink + Stream + FusedStream + New[|x: Fut| try_flatten::TryFlatten::new(x)] + where Fut: TryFuture +); + +#[cfg(feature = "sink")] +delegate_all!( + /// Sink for the [`flatten_sink`](TryFutureExt::flatten_sink) method. + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + FlattenSink( + try_flatten::TryFlatten + ): Debug + Sink + Stream + FusedStream + New[|x: Fut| try_flatten::TryFlatten::new(x)] +); + +delegate_all!( + /// Future for the [`and_then`](TryFutureExt::and_then) method. + AndThen( + TryFlatten, Fut2> + ): Debug + Future + FusedFuture + New[|x: Fut1, f: F| TryFlatten::new(MapOk::new(x, f))] +); + +delegate_all!( + /// Future for the [`or_else`](TryFutureExt::or_else) method. + OrElse( + TryFlattenErr, Fut2> + ): Debug + Future + FusedFuture + New[|x: Fut1, f: F| TryFlattenErr::new(MapErr::new(x, f))] +); + +delegate_all!( + /// Future for the [`err_into`](TryFutureExt::err_into) method. + ErrInto( + MapErr> + ): Debug + Future + FusedFuture + New[|x: Fut| MapErr::new(x, into_fn())] +); + +delegate_all!( + /// Future for the [`ok_into`](TryFutureExt::ok_into) method. + OkInto( + MapOk> + ): Debug + Future + FusedFuture + New[|x: Fut| MapOk::new(x, into_fn())] +); + +delegate_all!( + /// Future for the [`inspect_ok`](super::TryFutureExt::inspect_ok) method. + InspectOk( + Inspect, InspectOkFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Inspect::new(IntoFuture::new(x), inspect_ok_fn(f))] +); + +delegate_all!( + /// Future for the [`inspect_err`](super::TryFutureExt::inspect_err) method. + InspectErr( + Inspect, InspectErrFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Inspect::new(IntoFuture::new(x), inspect_err_fn(f))] +); + +#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 +pub use self::into_future::IntoFuture; + +delegate_all!( + /// Future for the [`map_ok`](TryFutureExt::map_ok) method. + MapOk( + Map, MapOkFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), map_ok_fn(f))] +); + +delegate_all!( + /// Future for the [`map_err`](TryFutureExt::map_err) method. + MapErr( + Map, MapErrFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), map_err_fn(f))] +); + +delegate_all!( + /// Future for the [`map_ok_or_else`](TryFutureExt::map_ok_or_else) method. + MapOkOrElse( + Map, MapOkOrElseFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F, g: G| Map::new(IntoFuture::new(x), map_ok_or_else_fn(f, g))] +); + +delegate_all!( + /// Future for the [`unwrap_or_else`](TryFutureExt::unwrap_or_else) method. + UnwrapOrElse( + Map, UnwrapOrElseFn> + ): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), unwrap_or_else_fn(f))] +); + +impl TryFutureExt for Fut {} + +/// Adapters specific to [`Result`]-returning futures +pub trait TryFutureExt: TryFuture { + /// Flattens the execution of this future when the successful result of this + /// future is a [`Sink`]. + /// + /// This can be useful when sink initialization is deferred, and it is + /// convenient to work with that sink as if the sink was available at the + /// call site. + /// + /// Note that this function consumes this future and returns a wrapped + /// version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::{Future, TryFutureExt}; + /// use futures::sink::Sink; + /// # use futures::channel::mpsc::{self, SendError}; + /// # type T = i32; + /// # type E = SendError; + /// + /// fn make_sink_async() -> impl Future, + /// E, + /// >> { // ... } + /// # let (tx, _rx) = mpsc::unbounded::(); + /// # futures::future::ready(Ok(tx)) + /// # } + /// fn take_sink(sink: impl Sink) { /* ... */ } + /// + /// let fut = make_sink_async(); + /// take_sink(fut.flatten_sink()) + /// ``` + #[cfg(feature = "sink")] + #[cfg_attr(docsrs, doc(cfg(feature = "sink")))] + fn flatten_sink(self) -> FlattenSink + where + Self::Ok: Sink, + Self: Sized, + { + crate::sink::assert_sink::(FlattenSink::new(self)) + } + + /// Maps this future's success value to a different value. + /// + /// This method can be used to change the [`Ok`](TryFuture::Ok) type of the + /// future into a different type. It is similar to the [`Result::map`] + /// method. You can use this method to chain along a computation once the + /// future has been resolved. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Ok`]. If it resolves to an [`Err`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.map_ok(|x| x + 3); + /// assert_eq!(future.await, Ok(4)); + /// # }); + /// ``` + /// + /// Calling [`map_ok`](TryFutureExt::map_ok) on an errored future has no + /// effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.map_ok(|x| x + 3); + /// assert_eq!(future.await, Err(1)); + /// # }); + /// ``` + fn map_ok(self, f: F) -> MapOk + where + F: FnOnce(Self::Ok) -> T, + Self: Sized, + { + assert_future::, _>(MapOk::new(self, f)) + } + + /// Maps this future's success value to a different value, and permits for error handling resulting in the same type. + /// + /// This method can be used to coalesce your [`Ok`](TryFuture::Ok) type and [`Error`](TryFuture::Error) into another type, + /// where that type is the same for both outcomes. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Ok`]. If it resolves to an [`Err`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// The provided closure `e` will only be called if this future is resolved + /// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(5) }; + /// let future = future.map_ok_or_else(|x| x * 2, |x| x + 3); + /// assert_eq!(future.await, 8); + /// + /// let future = async { Err::(5) }; + /// let future = future.map_ok_or_else(|x| x * 2, |x| x + 3); + /// assert_eq!(future.await, 10); + /// # }); + /// ``` + /// + fn map_ok_or_else(self, e: E, f: F) -> MapOkOrElse + where + F: FnOnce(Self::Ok) -> T, + E: FnOnce(Self::Error) -> T, + Self: Sized, + { + assert_future::(MapOkOrElse::new(self, f, e)) + } + + /// Maps this future's error value to a different value. + /// + /// This method can be used to change the [`Error`](TryFuture::Error) type + /// of the future into a different type. It is similar to the + /// [`Result::map_err`] method. You can use this method for example to + /// ensure that futures have the same [`Error`](TryFuture::Error) type when + /// using [`select!`] or [`join!`]. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then + /// the provided closure will never be invoked. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.map_err(|x| x + 3); + /// assert_eq!(future.await, Err(4)); + /// # }); + /// ``` + /// + /// Calling [`map_err`](TryFutureExt::map_err) on a successful future has + /// no effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.map_err(|x| x + 3); + /// assert_eq!(future.await, Ok(1)); + /// # }); + /// ``` + /// + /// [`join!`]: crate::join + /// [`select!`]: crate::select + fn map_err(self, f: F) -> MapErr + where + F: FnOnce(Self::Error) -> E, + Self: Sized, + { + assert_future::, _>(MapErr::new(self, f)) + } + + /// Maps this future's [`Error`](TryFuture::Error) to a new error type + /// using the [`Into`](std::convert::Into) trait. + /// + /// This method does for futures what the `?`-operator does for + /// [`Result`]: It lets the compiler infer the type of the resulting + /// error. Just as [`map_err`](TryFutureExt::map_err), this is useful for + /// example to ensure that futures have the same [`Error`](TryFuture::Error) + /// type when using [`select!`] or [`join!`]. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future_err_u8 = async { Err::<(), u8>(1) }; + /// let future_err_i32 = future_err_u8.err_into::(); + /// # }); + /// ``` + /// + /// [`join!`]: crate::join + /// [`select!`]: crate::select + fn err_into(self) -> ErrInto + where + Self: Sized, + Self::Error: Into, + { + assert_future::, _>(ErrInto::new(self)) + } + + /// Maps this future's [`Ok`](TryFuture::Ok) to a new type + /// using the [`Into`](std::convert::Into) trait. + fn ok_into(self) -> OkInto + where + Self: Sized, + Self::Ok: Into, + { + assert_future::, _>(OkInto::new(self)) + } + + /// Executes another future after this one resolves successfully. The + /// success value is passed to a closure to create this subsequent future. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Ok`]. If this future resolves to an [`Err`], panics, or is + /// dropped, then the provided closure will never be invoked. The + /// [`Error`](TryFuture::Error) type of this future and the future + /// returned by `f` have to match. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.and_then(|x| async move { Ok::(x + 3) }); + /// assert_eq!(future.await, Ok(4)); + /// # }); + /// ``` + /// + /// Calling [`and_then`](TryFutureExt::and_then) on an errored future has no + /// effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.and_then(|x| async move { Err::(x + 3) }); + /// assert_eq!(future.await, Err(1)); + /// # }); + /// ``` + fn and_then(self, f: F) -> AndThen + where + F: FnOnce(Self::Ok) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_future::, _>(AndThen::new(self, f)) + } + + /// Executes another future if this one resolves to an error. The + /// error value is passed to a closure to create this subsequent future. + /// + /// The provided closure `f` will only be called if this future is resolved + /// to an [`Err`]. If this future resolves to an [`Ok`], panics, or is + /// dropped, then the provided closure will never be invoked. The + /// [`Ok`](TryFuture::Ok) type of this future and the future returned by `f` + /// have to match. + /// + /// Note that this method consumes the future it is called on and returns a + /// wrapped version of it. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::(1) }; + /// let future = future.or_else(|x| async move { Err::(x + 3) }); + /// assert_eq!(future.await, Err(4)); + /// # }); + /// ``` + /// + /// Calling [`or_else`](TryFutureExt::or_else) on a successful future has + /// no effect: + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Ok::(1) }; + /// let future = future.or_else(|x| async move { Ok::(x + 3) }); + /// assert_eq!(future.await, Ok(1)); + /// # }); + /// ``` + fn or_else(self, f: F) -> OrElse + where + F: FnOnce(Self::Error) -> Fut, + Fut: TryFuture, + Self: Sized, + { + assert_future::, _>(OrElse::new(self, f)) + } + + /// Do something with the success value of a future before passing it on. + /// + /// When using futures, you'll often chain several of them together. While + /// working on such code, you might want to check out what's happening at + /// various parts in the pipeline, without consuming the intermediate + /// value. To do that, insert a call to `inspect_ok`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::TryFutureExt; + /// + /// let future = async { Ok::<_, ()>(1) }; + /// let new_future = future.inspect_ok(|&x| println!("about to resolve: {}", x)); + /// assert_eq!(new_future.await, Ok(1)); + /// # }); + /// ``` + fn inspect_ok(self, f: F) -> InspectOk + where + F: FnOnce(&Self::Ok), + Self: Sized, + { + assert_future::, _>(InspectOk::new(self, f)) + } + + /// Do something with the error value of a future before passing it on. + /// + /// When using futures, you'll often chain several of them together. While + /// working on such code, you might want to check out what's happening at + /// various parts in the pipeline, without consuming the intermediate + /// value. To do that, insert a call to `inspect_err`. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::TryFutureExt; + /// + /// let future = async { Err::<(), _>(1) }; + /// let new_future = future.inspect_err(|&x| println!("about to error: {}", x)); + /// assert_eq!(new_future.await, Err(1)); + /// # }); + /// ``` + fn inspect_err(self, f: F) -> InspectErr + where + F: FnOnce(&Self::Error), + Self: Sized, + { + assert_future::, _>(InspectErr::new(self, f)) + } + + /// Flatten the execution of this future when the successful result of this + /// future is another future. + /// + /// This is equivalent to `future.and_then(|x| x)`. + fn try_flatten(self) -> TryFlatten + where + Self::Ok: TryFuture, + Self: Sized, + { + assert_future::::Ok, Self::Error>, _>(TryFlatten::new(self)) + } + + /// Flatten the execution of this future when the successful result of this + /// future is a stream. + /// + /// This can be useful when stream initialization is deferred, and it is + /// convenient to work with that stream as if stream was available at the + /// call site. + /// + /// Note that this function consumes this future and returns a wrapped + /// version of it. + /// + /// # Examples + /// + /// ``` + /// # futures::executor::block_on(async { + /// use futures::future::TryFutureExt; + /// use futures::stream::{self, TryStreamExt}; + /// + /// let stream_items = vec![17, 18, 19].into_iter().map(Ok); + /// let future_of_a_stream = async { Ok::<_, ()>(stream::iter(stream_items)) }; + /// + /// let stream = future_of_a_stream.try_flatten_stream(); + /// let list = stream.try_collect::>().await; + /// assert_eq!(list, Ok(vec![17, 18, 19])); + /// # }); + /// ``` + fn try_flatten_stream(self) -> TryFlattenStream + where + Self::Ok: TryStream, + Self: Sized, + { + assert_stream::::Ok, Self::Error>, _>(TryFlattenStream::new( + self, + )) + } + + /// Unwraps this future's output, producing a future with this future's + /// [`Ok`](TryFuture::Ok) type as its + /// [`Output`](std::future::Future::Output) type. + /// + /// If this future is resolved successfully, the returned future will + /// contain the original future's success value as output. Otherwise, the + /// closure `f` is called with the error value to produce an alternate + /// success value. + /// + /// This method is similar to the [`Result::unwrap_or_else`] method. + /// + /// # Examples + /// + /// ``` + /// use futures::future::TryFutureExt; + /// + /// # futures::executor::block_on(async { + /// let future = async { Err::<(), &str>("Boom!") }; + /// let future = future.unwrap_or_else(|_| ()); + /// assert_eq!(future.await, ()); + /// # }); + /// ``` + fn unwrap_or_else(self, f: F) -> UnwrapOrElse + where + Self: Sized, + F: FnOnce(Self::Error) -> Self::Ok, + { + assert_future::(UnwrapOrElse::new(self, f)) + } + + /// Wraps a [`TryFuture`] into a future compatible with libraries using + /// futures 0.1 future definitions. Requires the `compat` feature to enable. + #[cfg(feature = "compat")] + #[cfg_attr(docsrs, doc(cfg(feature = "compat")))] + fn compat(self) -> Compat + where + Self: Sized + Unpin, + { + Compat::new(self) + } + + /// Wraps a [`TryFuture`] into a type that implements + /// [`Future`](std::future::Future). + /// + /// [`TryFuture`]s currently do not implement the + /// [`Future`](std::future::Future) trait due to limitations of the + /// compiler. + /// + /// # Examples + /// + /// ``` + /// use futures::future::{Future, TryFuture, TryFutureExt}; + /// + /// # type T = i32; + /// # type E = (); + /// fn make_try_future() -> impl TryFuture { // ... } + /// # async { Ok::(1) } + /// # } + /// fn take_future(future: impl Future>) { /* ... */ } + /// + /// take_future(make_try_future().into_future()); + /// ``` + fn into_future(self) -> IntoFuture + where + Self: Sized, + { + assert_future::, _>(IntoFuture::new(self)) + } + + /// A convenience method for calling [`TryFuture::try_poll`] on [`Unpin`] + /// future types. + fn try_poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll> + where + Self: Unpin, + { + Pin::new(self).try_poll(cx) + } +} diff --git a/third_party/rust/futures-util/src/future/try_future/try_flatten.rs b/third_party/rust/futures-util/src/future/try_future/try_flatten.rs new file mode 100644 index 0000000000..1ce4559ac2 --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_future/try_flatten.rs @@ -0,0 +1,162 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::stream::{FusedStream, Stream, TryStream}; +use futures_core::task::{Context, Poll}; +#[cfg(feature = "sink")] +use futures_sink::Sink; +use pin_project_lite::pin_project; + +pin_project! { + #[project = TryFlattenProj] + #[derive(Debug)] + pub enum TryFlatten { + First { #[pin] f: Fut1 }, + Second { #[pin] f: Fut2 }, + Empty, + } +} + +impl TryFlatten { + pub(crate) fn new(future: Fut1) -> Self { + Self::First { f: future } + } +} + +impl FusedFuture for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryFuture, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Future for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryFuture, +{ + type Output = Result<::Ok, Fut::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenProj::First { f } => match ready!(f.try_poll(cx)) { + Ok(f) => self.set(Self::Second { f }), + Err(e) => { + self.set(Self::Empty); + break Err(e); + } + }, + TryFlattenProj::Second { f } => { + let output = ready!(f.try_poll(cx)); + self.set(Self::Empty); + break output; + } + TryFlattenProj::Empty => panic!("TryFlatten polled after completion"), + } + }) + } +} + +impl FusedStream for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryStream, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Stream for TryFlatten +where + Fut: TryFuture, + Fut::Ok: TryStream, +{ + type Item = Result<::Ok, Fut::Error>; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenProj::First { f } => match ready!(f.try_poll(cx)) { + Ok(f) => self.set(Self::Second { f }), + Err(e) => { + self.set(Self::Empty); + break Some(Err(e)); + } + }, + TryFlattenProj::Second { f } => { + let output = ready!(f.try_poll_next(cx)); + if output.is_none() { + self.set(Self::Empty); + } + break output; + } + TryFlattenProj::Empty => break None, + } + }) + } +} + +#[cfg(feature = "sink")] +impl Sink for TryFlatten +where + Fut: TryFuture, + Fut::Ok: Sink, +{ + type Error = Fut::Error; + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenProj::First { f } => match ready!(f.try_poll(cx)) { + Ok(f) => self.set(Self::Second { f }), + Err(e) => { + self.set(Self::Empty); + break Err(e); + } + }, + TryFlattenProj::Second { f } => { + break ready!(f.poll_ready(cx)); + } + TryFlattenProj::Empty => panic!("poll_ready called after eof"), + } + }) + } + + fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> { + match self.project() { + TryFlattenProj::First { .. } => panic!("poll_ready not called first"), + TryFlattenProj::Second { f } => f.start_send(item), + TryFlattenProj::Empty => panic!("start_send called after eof"), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.project() { + TryFlattenProj::First { .. } => Poll::Ready(Ok(())), + TryFlattenProj::Second { f } => f.poll_flush(cx), + TryFlattenProj::Empty => panic!("poll_flush called after eof"), + } + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let res = match self.as_mut().project() { + TryFlattenProj::Second { f } => f.poll_close(cx), + _ => Poll::Ready(Ok(())), + }; + if res.is_ready() { + self.set(Self::Empty); + } + res + } +} diff --git a/third_party/rust/futures-util/src/future/try_future/try_flatten_err.rs b/third_party/rust/futures-util/src/future/try_future/try_flatten_err.rs new file mode 100644 index 0000000000..39b7d9f5f6 --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_future/try_flatten_err.rs @@ -0,0 +1,62 @@ +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +pin_project! { + #[project = TryFlattenErrProj] + #[derive(Debug)] + pub enum TryFlattenErr { + First { #[pin] f: Fut1 }, + Second { #[pin] f: Fut2 }, + Empty, + } +} + +impl TryFlattenErr { + pub(crate) fn new(future: Fut1) -> Self { + Self::First { f: future } + } +} + +impl FusedFuture for TryFlattenErr +where + Fut: TryFuture, + Fut::Error: TryFuture, +{ + fn is_terminated(&self) -> bool { + match self { + Self::Empty => true, + _ => false, + } + } +} + +impl Future for TryFlattenErr +where + Fut: TryFuture, + Fut::Error: TryFuture, +{ + type Output = Result::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Poll::Ready(loop { + match self.as_mut().project() { + TryFlattenErrProj::First { f } => match ready!(f.try_poll(cx)) { + Err(f) => self.set(Self::Second { f }), + Ok(e) => { + self.set(Self::Empty); + break Ok(e); + } + }, + TryFlattenErrProj::Second { f } => { + let output = ready!(f.try_poll(cx)); + self.set(Self::Empty); + break output; + } + TryFlattenErrProj::Empty => panic!("TryFlattenErr polled after completion"), + } + }) + } +} diff --git a/third_party/rust/futures-util/src/future/try_join.rs b/third_party/rust/futures-util/src/future/try_join.rs new file mode 100644 index 0000000000..6af1f0ccbf --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_join.rs @@ -0,0 +1,256 @@ +#![allow(non_snake_case)] + +use crate::future::{assert_future, try_maybe_done, TryMaybeDone}; +use core::fmt; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::task::{Context, Poll}; +use pin_project_lite::pin_project; + +macro_rules! generate { + ($( + $(#[$doc:meta])* + ($Join:ident, ), + )*) => ($( + pin_project! { + $(#[$doc])* + #[must_use = "futures do nothing unless you `.await` or poll them"] + pub struct $Join { + #[pin] Fut1: TryMaybeDone, + $(#[pin] $Fut: TryMaybeDone<$Fut>,)* + } + } + + impl fmt::Debug for $Join + where + Fut1: TryFuture + fmt::Debug, + Fut1::Ok: fmt::Debug, + Fut1::Error: fmt::Debug, + $( + $Fut: TryFuture + fmt::Debug, + $Fut::Ok: fmt::Debug, + $Fut::Error: fmt::Debug, + )* + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct(stringify!($Join)) + .field("Fut1", &self.Fut1) + $(.field(stringify!($Fut), &self.$Fut))* + .finish() + } + } + + impl $Join + where + Fut1: TryFuture, + $( + $Fut: TryFuture + ),* + { + fn new(Fut1: Fut1, $($Fut: $Fut),*) -> Self { + Self { + Fut1: try_maybe_done(Fut1), + $($Fut: try_maybe_done($Fut)),* + } + } + } + + impl Future for $Join + where + Fut1: TryFuture, + $( + $Fut: TryFuture + ),* + { + type Output = Result<(Fut1::Ok, $($Fut::Ok),*), Fut1::Error>; + + fn poll( + self: Pin<&mut Self>, cx: &mut Context<'_> + ) -> Poll { + let mut all_done = true; + let mut futures = self.project(); + all_done &= futures.Fut1.as_mut().poll(cx)?.is_ready(); + $( + all_done &= futures.$Fut.as_mut().poll(cx)?.is_ready(); + )* + + if all_done { + Poll::Ready(Ok(( + futures.Fut1.take_output().unwrap(), + $( + futures.$Fut.take_output().unwrap() + ),* + ))) + } else { + Poll::Pending + } + } + } + )*) +} + +generate! { + /// Future for the [`try_join`](try_join()) function. + (TryJoin, ), + + /// Future for the [`try_join3`] function. + (TryJoin3, ), + + /// Future for the [`try_join4`] function. + (TryJoin4, ), + + /// Future for the [`try_join5`] function. + (TryJoin5, ), +} + +/// Joins the result of two futures, waiting for them both to complete or +/// for one to produce an error. +/// +/// This function will return a new future which awaits both futures to +/// complete. If successful, the returned future will finish with a tuple of +/// both results. If unsuccessful, it will complete with the first error +/// encountered. +/// +/// Note that this function consumes the passed futures and returns a +/// wrapped version of it. +/// +/// # Examples +/// +/// When used on multiple futures that return [`Ok`], `try_join` will return +/// [`Ok`] of a tuple of the values: +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let pair = future::try_join(a, b); +/// +/// assert_eq!(pair.await, Ok((1, 2))); +/// # }); +/// ``` +/// +/// If one of the futures resolves to an error, `try_join` will return +/// that error: +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Err::(2)); +/// let pair = future::try_join(a, b); +/// +/// assert_eq!(pair.await, Err(2)); +/// # }); +/// ``` +pub fn try_join(future1: Fut1, future2: Fut2) -> TryJoin +where + Fut1: TryFuture, + Fut2: TryFuture, +{ + assert_future::, _>(TryJoin::new(future1, future2)) +} + +/// Same as [`try_join`](try_join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let c = future::ready(Ok::(3)); +/// let tuple = future::try_join3(a, b, c); +/// +/// assert_eq!(tuple.await, Ok((1, 2, 3))); +/// # }); +/// ``` +pub fn try_join3( + future1: Fut1, + future2: Fut2, + future3: Fut3, +) -> TryJoin3 +where + Fut1: TryFuture, + Fut2: TryFuture, + Fut3: TryFuture, +{ + assert_future::, _>(TryJoin3::new( + future1, future2, future3, + )) +} + +/// Same as [`try_join`](try_join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let c = future::ready(Ok::(3)); +/// let d = future::ready(Ok::(4)); +/// let tuple = future::try_join4(a, b, c, d); +/// +/// assert_eq!(tuple.await, Ok((1, 2, 3, 4))); +/// # }); +/// ``` +pub fn try_join4( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, +) -> TryJoin4 +where + Fut1: TryFuture, + Fut2: TryFuture, + Fut3: TryFuture, + Fut4: TryFuture, +{ + assert_future::, _>( + TryJoin4::new(future1, future2, future3, future4), + ) +} + +/// Same as [`try_join`](try_join()), but with more futures. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future; +/// +/// let a = future::ready(Ok::(1)); +/// let b = future::ready(Ok::(2)); +/// let c = future::ready(Ok::(3)); +/// let d = future::ready(Ok::(4)); +/// let e = future::ready(Ok::(5)); +/// let tuple = future::try_join5(a, b, c, d, e); +/// +/// assert_eq!(tuple.await, Ok((1, 2, 3, 4, 5))); +/// # }); +/// ``` +pub fn try_join5( + future1: Fut1, + future2: Fut2, + future3: Fut3, + future4: Fut4, + future5: Fut5, +) -> TryJoin5 +where + Fut1: TryFuture, + Fut2: TryFuture, + Fut3: TryFuture, + Fut4: TryFuture, + Fut5: TryFuture, +{ + assert_future::, _>( + TryJoin5::new(future1, future2, future3, future4, future5), + ) +} diff --git a/third_party/rust/futures-util/src/future/try_join_all.rs b/third_party/rust/futures-util/src/future/try_join_all.rs new file mode 100644 index 0000000000..506f450657 --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_join_all.rs @@ -0,0 +1,200 @@ +//! Definition of the `TryJoinAll` combinator, waiting for all of a list of +//! futures to finish with either success or error. + +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::fmt; +use core::future::Future; +use core::iter::FromIterator; +use core::mem; +use core::pin::Pin; +use core::task::{Context, Poll}; + +use super::{assert_future, join_all, IntoFuture, TryFuture, TryMaybeDone}; + +#[cfg(not(futures_no_atomic_cas))] +use crate::stream::{FuturesOrdered, TryCollect, TryStreamExt}; +use crate::TryFutureExt; + +enum FinalState { + Pending, + AllDone, + Error(E), +} + +/// Future for the [`try_join_all`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct TryJoinAll +where + F: TryFuture, +{ + kind: TryJoinAllKind, +} + +enum TryJoinAllKind +where + F: TryFuture, +{ + Small { + elems: Pin>]>>, + }, + #[cfg(not(futures_no_atomic_cas))] + Big { + fut: TryCollect>, Vec>, + }, +} + +impl fmt::Debug for TryJoinAll +where + F: TryFuture + fmt::Debug, + F::Ok: fmt::Debug, + F::Error: fmt::Debug, + F::Output: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + TryJoinAllKind::Small { ref elems } => { + f.debug_struct("TryJoinAll").field("elems", elems).finish() + } + #[cfg(not(futures_no_atomic_cas))] + TryJoinAllKind::Big { ref fut, .. } => fmt::Debug::fmt(fut, f), + } + } +} + +/// Creates a future which represents either a collection of the results of the +/// futures given or an error. +/// +/// The returned future will drive execution for all of its underlying futures, +/// collecting the results into a destination `Vec` in the same order as they +/// were provided. +/// +/// If any future returns an error then all other futures will be canceled and +/// an error will be returned immediately. If all futures complete successfully, +/// however, then the returned future will succeed with a `Vec` of all the +/// successful results. +/// +/// This function is only available when the `std` or `alloc` feature of this +/// library is activated, and it is activated by default. +/// +/// # See Also +/// +/// `try_join_all` will switch to the more powerful [`FuturesOrdered`] for performance +/// reasons if the number of futures is large. You may want to look into using it or +/// it's counterpart [`FuturesUnordered`][crate::stream::FuturesUnordered] directly. +/// +/// Some examples for additional functionality provided by these are: +/// +/// * Adding new futures to the set even after it has been started. +/// +/// * Only polling the specific futures that have been woken. In cases where +/// you have a lot of futures this will result in much more efficient polling. +/// +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use futures::future::{self, try_join_all}; +/// +/// let futures = vec![ +/// future::ok::(1), +/// future::ok::(2), +/// future::ok::(3), +/// ]; +/// +/// assert_eq!(try_join_all(futures).await, Ok(vec![1, 2, 3])); +/// +/// let futures = vec![ +/// future::ok::(1), +/// future::err::(2), +/// future::ok::(3), +/// ]; +/// +/// assert_eq!(try_join_all(futures).await, Err(2)); +/// # }); +/// ``` +pub fn try_join_all(iter: I) -> TryJoinAll +where + I: IntoIterator, + I::Item: TryFuture, +{ + let iter = iter.into_iter().map(TryFutureExt::into_future); + + #[cfg(futures_no_atomic_cas)] + { + let kind = TryJoinAllKind::Small { + elems: iter.map(TryMaybeDone::Future).collect::>().into(), + }; + + assert_future::::Ok>, ::Error>, _>( + TryJoinAll { kind }, + ) + } + + #[cfg(not(futures_no_atomic_cas))] + { + let kind = match iter.size_hint().1 { + Some(max) if max <= join_all::SMALL => TryJoinAllKind::Small { + elems: iter.map(TryMaybeDone::Future).collect::>().into(), + }, + _ => TryJoinAllKind::Big { fut: iter.collect::>().try_collect() }, + }; + + assert_future::::Ok>, ::Error>, _>( + TryJoinAll { kind }, + ) + } +} + +impl Future for TryJoinAll +where + F: TryFuture, +{ + type Output = Result, F::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match &mut self.kind { + TryJoinAllKind::Small { elems } => { + let mut state = FinalState::AllDone; + + for elem in join_all::iter_pin_mut(elems.as_mut()) { + match elem.try_poll(cx) { + Poll::Pending => state = FinalState::Pending, + Poll::Ready(Ok(())) => {} + Poll::Ready(Err(e)) => { + state = FinalState::Error(e); + break; + } + } + } + + match state { + FinalState::Pending => Poll::Pending, + FinalState::AllDone => { + let mut elems = mem::replace(elems, Box::pin([])); + let results = join_all::iter_pin_mut(elems.as_mut()) + .map(|e| e.take_output().unwrap()) + .collect(); + Poll::Ready(Ok(results)) + } + FinalState::Error(e) => { + let _ = mem::replace(elems, Box::pin([])); + Poll::Ready(Err(e)) + } + } + } + #[cfg(not(futures_no_atomic_cas))] + TryJoinAllKind::Big { fut } => Pin::new(fut).poll(cx), + } + } +} + +impl FromIterator for TryJoinAll +where + F: TryFuture, +{ + fn from_iter>(iter: T) -> Self { + try_join_all(iter) + } +} diff --git a/third_party/rust/futures-util/src/future/try_maybe_done.rs b/third_party/rust/futures-util/src/future/try_maybe_done.rs new file mode 100644 index 0000000000..24044d2c27 --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_maybe_done.rs @@ -0,0 +1,92 @@ +//! Definition of the TryMaybeDone combinator + +use super::assert_future; +use core::mem; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future, TryFuture}; +use futures_core::ready; +use futures_core::task::{Context, Poll}; + +/// A future that may have completed with an error. +/// +/// This is created by the [`try_maybe_done()`] function. +#[derive(Debug)] +pub enum TryMaybeDone { + /// A not-yet-completed future + Future(/* #[pin] */ Fut), + /// The output of the completed future + Done(Fut::Ok), + /// The empty variant after the result of a [`TryMaybeDone`] has been + /// taken using the [`take_output`](TryMaybeDone::take_output) method, + /// or if the future returned an error. + Gone, +} + +impl Unpin for TryMaybeDone {} + +/// Wraps a future into a `TryMaybeDone` +pub fn try_maybe_done(future: Fut) -> TryMaybeDone { + assert_future::, _>(TryMaybeDone::Future(future)) +} + +impl TryMaybeDone { + /// Returns an [`Option`] containing a mutable reference to the output of the future. + /// The output of this method will be [`Some`] if and only if the inner + /// future has completed successfully and [`take_output`](TryMaybeDone::take_output) + /// has not yet been called. + #[inline] + pub fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Ok> { + unsafe { + match self.get_unchecked_mut() { + TryMaybeDone::Done(res) => Some(res), + _ => None, + } + } + } + + /// Attempt to take the output of a `TryMaybeDone` without driving it + /// towards completion. + #[inline] + pub fn take_output(self: Pin<&mut Self>) -> Option { + match &*self { + Self::Done(_) => {} + Self::Future(_) | Self::Gone => return None, + } + unsafe { + match mem::replace(self.get_unchecked_mut(), Self::Gone) { + TryMaybeDone::Done(output) => Some(output), + _ => unreachable!(), + } + } + } +} + +impl FusedFuture for TryMaybeDone { + fn is_terminated(&self) -> bool { + match self { + Self::Future(_) => false, + Self::Done(_) | Self::Gone => true, + } + } +} + +impl Future for TryMaybeDone { + type Output = Result<(), Fut::Error>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + unsafe { + match self.as_mut().get_unchecked_mut() { + TryMaybeDone::Future(f) => match ready!(Pin::new_unchecked(f).try_poll(cx)) { + Ok(res) => self.set(Self::Done(res)), + Err(e) => { + self.set(Self::Gone); + return Poll::Ready(Err(e)); + } + }, + TryMaybeDone::Done(_) => {} + TryMaybeDone::Gone => panic!("TryMaybeDone polled after value taken"), + } + } + Poll::Ready(Ok(())) + } +} diff --git a/third_party/rust/futures-util/src/future/try_select.rs b/third_party/rust/futures-util/src/future/try_select.rs new file mode 100644 index 0000000000..4d0b7ff135 --- /dev/null +++ b/third_party/rust/futures-util/src/future/try_select.rs @@ -0,0 +1,84 @@ +use crate::future::{Either, TryFutureExt}; +use core::pin::Pin; +use futures_core::future::{Future, TryFuture}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`try_select()`] function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +#[derive(Debug)] +pub struct TrySelect { + inner: Option<(A, B)>, +} + +impl Unpin for TrySelect {} + +/// Waits for either one of two differently-typed futures to complete. +/// +/// This function will return a new future which awaits for either one of both +/// futures to complete. The returned future will finish with both the value +/// resolved and a future representing the completion of the other work. +/// +/// Note that this function consumes the receiving futures and returns a +/// wrapped version of them. +/// +/// Also note that if both this and the second future have the same +/// success/error type you can use the `Either::factor_first` method to +/// conveniently extract out the value at the end. +/// +/// # Examples +/// +/// ``` +/// use futures::future::{self, Either, Future, FutureExt, TryFuture, TryFutureExt}; +/// +/// // A poor-man's try_join implemented on top of select +/// +/// fn try_join(a: A, b: B) -> impl TryFuture +/// where A: TryFuture + Unpin + 'static, +/// B: TryFuture + Unpin + 'static, +/// E: 'static, +/// { +/// future::try_select(a, b).then(|res| -> Box> + Unpin> { +/// match res { +/// Ok(Either::Left((x, b))) => Box::new(b.map_ok(move |y| (x, y))), +/// Ok(Either::Right((y, a))) => Box::new(a.map_ok(move |x| (x, y))), +/// Err(Either::Left((e, _))) => Box::new(future::err(e)), +/// Err(Either::Right((e, _))) => Box::new(future::err(e)), +/// } +/// }) +/// } +/// ``` +pub fn try_select(future1: A, future2: B) -> TrySelect +where + A: TryFuture + Unpin, + B: TryFuture + Unpin, +{ + super::assert_future::< + Result, Either<(A::Error, B), (B::Error, A)>>, + _, + >(TrySelect { inner: Some((future1, future2)) }) +} + +impl Future for TrySelect +where + A: TryFuture, + B: TryFuture, +{ + #[allow(clippy::type_complexity)] + type Output = Result, Either<(A::Error, B), (B::Error, A)>>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let (mut a, mut b) = self.inner.take().expect("cannot poll Select twice"); + match a.try_poll_unpin(cx) { + Poll::Ready(Err(x)) => Poll::Ready(Err(Either::Left((x, b)))), + Poll::Ready(Ok(x)) => Poll::Ready(Ok(Either::Left((x, b)))), + Poll::Pending => match b.try_poll_unpin(cx) { + Poll::Ready(Err(x)) => Poll::Ready(Err(Either::Right((x, a)))), + Poll::Ready(Ok(x)) => Poll::Ready(Ok(Either::Right((x, a)))), + Poll::Pending => { + self.inner = Some((a, b)); + Poll::Pending + } + }, + } + } +} -- cgit v1.2.3