RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
19
zeroidc/vendor/futures-util/src/future/abortable.rs
vendored
Normal file
19
zeroidc/vendor/futures-util/src/future/abortable.rs
vendored
Normal file
@@ -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<Fut>(future: Fut) -> (Abortable<Fut>, AbortHandle)
|
||||
where
|
||||
Fut: Future,
|
||||
{
|
||||
let (handle, reg) = AbortHandle::new_pair();
|
||||
let abortable = assert_future::<Result<Fut::Output, Aborted>, _>(Abortable::new(future, reg));
|
||||
(abortable, handle)
|
||||
}
|
||||
297
zeroidc/vendor/futures-util/src/future/either.rs
vendored
Normal file
297
zeroidc/vendor/futures-util/src/future/either.rs
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
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<A, B> {
|
||||
/// First branch of the type
|
||||
Left(/* #[pin] */ A),
|
||||
/// Second branch of the type
|
||||
Right(/* #[pin] */ B),
|
||||
}
|
||||
|
||||
impl<A, B> Either<A, B> {
|
||||
fn project(self: Pin<&mut Self>) -> Either<Pin<&mut A>, Pin<&mut B>> {
|
||||
unsafe {
|
||||
match self.get_unchecked_mut() {
|
||||
Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
|
||||
Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, T> 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<A, B>) {
|
||||
match self {
|
||||
Either::Left((x, a)) => (x, Either::Left(a)),
|
||||
Either::Right((x, b)) => (x, Either::Right(b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, T> 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<A, B>, T) {
|
||||
match self {
|
||||
Either::Left((a, x)) => (Either::Left(a), x),
|
||||
Either::Right((b, x)) => (Either::Right(b), x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Either<T, T> {
|
||||
/// 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<A, B> Future for Either<A, B>
|
||||
where
|
||||
A: Future,
|
||||
B: Future<Output = A::Output>,
|
||||
{
|
||||
type Output = A::Output;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.project() {
|
||||
Either::Left(x) => x.poll(cx),
|
||||
Either::Right(x) => x.poll(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> FusedFuture for Either<A, B>
|
||||
where
|
||||
A: FusedFuture,
|
||||
B: FusedFuture<Output = A::Output>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Either::Left(x) => x.is_terminated(),
|
||||
Either::Right(x) => x.is_terminated(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Stream for Either<A, B>
|
||||
where
|
||||
A: Stream,
|
||||
B: Stream<Item = A::Item>,
|
||||
{
|
||||
type Item = A::Item;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
match self.project() {
|
||||
Either::Left(x) => x.poll_next(cx),
|
||||
Either::Right(x) => x.poll_next(cx),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self {
|
||||
Either::Left(x) => x.size_hint(),
|
||||
Either::Right(x) => x.size_hint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> FusedStream for Either<A, B>
|
||||
where
|
||||
A: FusedStream,
|
||||
B: FusedStream<Item = A::Item>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Either::Left(x) => x.is_terminated(),
|
||||
Either::Right(x) => x.is_terminated(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<A, B, Item> Sink<Item> for Either<A, B>
|
||||
where
|
||||
A: Sink<Item>,
|
||||
B: Sink<Item, Error = A::Error>,
|
||||
{
|
||||
type Error = A::Error;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
match self.project() {
|
||||
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.project() {
|
||||
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<Result<(), Self::Error>> {
|
||||
match self.project() {
|
||||
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<Result<(), Self::Error>> {
|
||||
match self.project() {
|
||||
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<A, B> AsyncRead for Either<A, B>
|
||||
where
|
||||
A: AsyncRead,
|
||||
B: AsyncRead,
|
||||
{
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize>> {
|
||||
match self.project() {
|
||||
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<Result<usize>> {
|
||||
match self.project() {
|
||||
Either::Left(x) => x.poll_read_vectored(cx, bufs),
|
||||
Either::Right(x) => x.poll_read_vectored(cx, bufs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> AsyncWrite for Either<A, B>
|
||||
where
|
||||
A: AsyncWrite,
|
||||
B: AsyncWrite,
|
||||
{
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize>> {
|
||||
match self.project() {
|
||||
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<Result<usize>> {
|
||||
match self.project() {
|
||||
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<Result<()>> {
|
||||
match self.project() {
|
||||
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<Result<()>> {
|
||||
match self.project() {
|
||||
Either::Left(x) => x.poll_close(cx),
|
||||
Either::Right(x) => x.poll_close(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> AsyncSeek for Either<A, B>
|
||||
where
|
||||
A: AsyncSeek,
|
||||
B: AsyncSeek,
|
||||
{
|
||||
fn poll_seek(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
pos: SeekFrom,
|
||||
) -> Poll<Result<u64>> {
|
||||
match self.project() {
|
||||
Either::Left(x) => x.poll_seek(cx, pos),
|
||||
Either::Right(x) => x.poll_seek(cx, pos),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> AsyncBufRead for Either<A, B>
|
||||
where
|
||||
A: AsyncBufRead,
|
||||
B: AsyncBufRead,
|
||||
{
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
|
||||
match self.project() {
|
||||
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.project() {
|
||||
Either::Left(x) => x.consume(amt),
|
||||
Either::Right(x) => x.consume(amt),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
zeroidc/vendor/futures-util/src/future/future/catch_unwind.rs
vendored
Normal file
38
zeroidc/vendor/futures-util/src/future/future/catch_unwind.rs
vendored
Normal file
@@ -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<Fut> {
|
||||
#[pin]
|
||||
future: Fut,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> CatchUnwind<Fut>
|
||||
where
|
||||
Fut: Future + UnwindSafe,
|
||||
{
|
||||
pub(super) fn new(future: Fut) -> Self {
|
||||
Self { future }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for CatchUnwind<Fut>
|
||||
where
|
||||
Fut: Future + UnwindSafe,
|
||||
{
|
||||
type Output = Result<Fut::Output, Box<dyn Any + Send>>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let f = self.project().future;
|
||||
catch_unwind(AssertUnwindSafe(|| f.poll(cx)))?.map(Ok)
|
||||
}
|
||||
}
|
||||
153
zeroidc/vendor/futures-util/src/future/future/flatten.rs
vendored
Normal file
153
zeroidc/vendor/futures-util/src/future/future/flatten.rs
vendored
Normal file
@@ -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<Fut1, Fut2> {
|
||||
First { #[pin] f: Fut1 },
|
||||
Second { #[pin] f: Fut2 },
|
||||
Empty,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut1, Fut2> Flatten<Fut1, Fut2> {
|
||||
pub(crate) fn new(future: Fut1) -> Self {
|
||||
Self::First { f: future }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> FusedFuture for Flatten<Fut, Fut::Output>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Future,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Empty => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for Flatten<Fut, Fut::Output>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Future,
|
||||
{
|
||||
type Output = <Fut::Output as Future>::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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<Fut> FusedStream for Flatten<Fut, Fut::Output>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Stream,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Empty => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Stream for Flatten<Fut, Fut::Output>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Stream,
|
||||
{
|
||||
type Item = <Fut::Output as Stream>::Item;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
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<Fut, Item> Sink<Item> for Flatten<Fut, Fut::Output>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Sink<Item>,
|
||||
{
|
||||
type Error = <Fut::Output as Sink<Item>>::Error;
|
||||
|
||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
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<Result<(), Self::Error>> {
|
||||
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<Result<(), Self::Error>> {
|
||||
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
|
||||
}
|
||||
}
|
||||
93
zeroidc/vendor/futures-util/src/future/future/fuse.rs
vendored
Normal file
93
zeroidc/vendor/futures-util/src/future/future/fuse.rs
vendored
Normal file
@@ -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<Fut> {
|
||||
#[pin]
|
||||
inner: Option<Fut>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Fuse<Fut> {
|
||||
pub(super) fn new(f: Fut) -> Self {
|
||||
Self { inner: Some(f) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Fuse<Fut> {
|
||||
/// 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<Fut: Future> FusedFuture for Fuse<Fut> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.inner.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Future for Fuse<Fut> {
|
||||
type Output = Fut::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output> {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
66
zeroidc/vendor/futures-util/src/future/future/map.rs
vendored
Normal file
66
zeroidc/vendor/futures-util/src/future/future/map.rs
vendored
Normal file
@@ -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<Fut, F> {
|
||||
Incomplete {
|
||||
#[pin]
|
||||
future: Fut,
|
||||
f: F,
|
||||
},
|
||||
Complete,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut, F> Map<Fut, F> {
|
||||
/// Creates a new Map.
|
||||
pub(crate) fn new(future: Fut, f: F) -> Self {
|
||||
Self::Incomplete { future, f }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut, F, T> FusedFuture for Map<Fut, F>
|
||||
where
|
||||
Fut: Future,
|
||||
F: FnOnce1<Fut::Output, Output = T>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Incomplete { .. } => false,
|
||||
Self::Complete => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut, F, T> Future for Map<Fut, F>
|
||||
where
|
||||
Fut: Future,
|
||||
F: FnOnce1<Fut::Output, Output = T>,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
|
||||
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`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
610
zeroidc/vendor/futures-util/src/future/future/mod.rs
vendored
Normal file
610
zeroidc/vendor/futures-util/src/future/future/mod.rs
vendored
Normal file
@@ -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<F>(
|
||||
flatten::Flatten<F, <F as Future>::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<F>(
|
||||
flatten::Flatten<F, <F as Future>::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<Fut, F>(
|
||||
map::Map<Fut, F>
|
||||
): 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<F>(
|
||||
crate::stream::Once<F>
|
||||
): Debug + Stream + FusedStream + New[|x: F| crate::stream::Once::new(x)]
|
||||
);
|
||||
|
||||
delegate_all!(
|
||||
/// Future for the [`map_into`](FutureExt::map_into) combinator.
|
||||
MapInto<Fut, T>(
|
||||
Map<Fut, IntoFn<T>>
|
||||
): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, into_fn())]
|
||||
);
|
||||
|
||||
delegate_all!(
|
||||
/// Future for the [`then`](FutureExt::then) method.
|
||||
Then<Fut1, Fut2, F>(
|
||||
flatten::Flatten<Map<Fut1, F>, 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<Fut, F>(
|
||||
map::Map<Fut, InspectFn<F>>
|
||||
): 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<Fut>(
|
||||
Map<Fut, OkFn<Never>>
|
||||
): Debug + Future + FusedFuture + New[|x: Fut| Map::new(x, ok_fn())]
|
||||
);
|
||||
|
||||
delegate_all!(
|
||||
/// Future for the [`unit_error`](super::FutureExt::unit_error) combinator.
|
||||
UnitError<Fut>(
|
||||
Map<Fut, OkFn<()>>
|
||||
): 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<T: ?Sized> 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<U, F>(self, f: F) -> Map<Self, F>
|
||||
where
|
||||
F: FnOnce(Self::Output) -> U,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<U, _>(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<U>(self) -> MapInto<Self, U>
|
||||
where
|
||||
Self::Output: Into<U>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<U, _>(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<Fut, F>(self, f: F) -> Then<Self, Fut, F>
|
||||
where
|
||||
F: FnOnce(Self::Output) -> Fut,
|
||||
Fut: Future,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Fut::Output, _>(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<B>(self) -> Either<Self, B>
|
||||
where
|
||||
B: Future<Output = Self::Output>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Self::Output, _>(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<A>(self) -> Either<A, Self>
|
||||
where
|
||||
A: Future<Output = Self::Output>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Self::Output, _>(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<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_stream::<Self::Output, _>(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<Self>
|
||||
where
|
||||
Self::Output: Future,
|
||||
Self: Sized,
|
||||
{
|
||||
let f = Flatten::new(self);
|
||||
assert_future::<<<Self as 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<Self>
|
||||
where
|
||||
Self::Output: Stream,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_stream::<<Self::Output as 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<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let f = Fuse::new(self);
|
||||
assert_future::<Self::Output, _>(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<F>(self, f: F) -> Inspect<Self, F>
|
||||
where
|
||||
F: FnOnce(&Self::Output),
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Self::Output, _>(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<F>` 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<i32> {
|
||||
/// unimplemented!()
|
||||
/// });
|
||||
/// assert!(future.catch_unwind().await.is_err());
|
||||
/// # });
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
fn catch_unwind(self) -> CatchUnwind<Self>
|
||||
where
|
||||
Self: Sized + ::std::panic::UnwindSafe,
|
||||
{
|
||||
assert_future::<Result<Self::Output, Box<dyn std::any::Any + Send>>, _>(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<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Output: Clone,
|
||||
{
|
||||
assert_future::<Self::Output, _>(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<Self>, RemoteHandle<Self::Output>)
|
||||
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::<Self::Output, _>(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::<Self::Output, _>(Box::pin(self))
|
||||
}
|
||||
|
||||
/// Turns a [`Future<Output = T>`](Future) into a
|
||||
/// [`TryFuture<Ok = T, Error = ()`>](futures_core::future::TryFuture).
|
||||
fn unit_error(self) -> UnitError<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Self::Output, ()>, _>(UnitError::new(self))
|
||||
}
|
||||
|
||||
/// Turns a [`Future<Output = T>`](Future) into a
|
||||
/// [`TryFuture<Ok = T, Error = Never`>](futures_core::future::TryFuture).
|
||||
fn never_error(self) -> NeverError<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Self::Output, Never>, _>(NeverError::new(self))
|
||||
}
|
||||
|
||||
/// A convenience for calling `Future::poll` on `Unpin` future types.
|
||||
fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
|
||||
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<Self::Output>
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
126
zeroidc/vendor/futures-util/src/future/future/remote_handle.rs
vendored
Normal file
126
zeroidc/vendor/futures-util/src/future/future/remote_handle.rs
vendored
Normal file
@@ -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<T> {
|
||||
rx: Receiver<thread::Result<T>>,
|
||||
keep_running: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl<T> RemoteHandle<T> {
|
||||
/// 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<T: 'static> Future for RemoteHandle<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
|
||||
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<Fut> = Result<<Fut as Future>::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<Fut: Future> {
|
||||
tx: Option<Sender<SendMsg<Fut>>>,
|
||||
keep_running: Arc<AtomicBool>,
|
||||
#[pin]
|
||||
future: CatchUnwind<AssertUnwindSafe<Fut>>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future + fmt::Debug> fmt::Debug for Remote<Fut> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Remote").field(&self.future).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Future for Remote<Fut> {
|
||||
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<Fut: Future>(future: Fut) -> (Remote<Fut>, RemoteHandle<Fut::Output>) {
|
||||
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 })
|
||||
}
|
||||
371
zeroidc/vendor/futures-util/src/future/future/shared.rs
vendored
Normal file
371
zeroidc/vendor/futures-util/src/future/future/shared.rs
vendored
Normal file
@@ -0,0 +1,371 @@
|
||||
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::pin::Pin;
|
||||
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<Fut: Future> {
|
||||
inner: Option<Arc<Inner<Fut>>>,
|
||||
waker_key: usize,
|
||||
}
|
||||
|
||||
struct Inner<Fut: Future> {
|
||||
future_or_output: UnsafeCell<FutureOrOutput<Fut>>,
|
||||
notifier: Arc<Notifier>,
|
||||
}
|
||||
|
||||
struct Notifier {
|
||||
state: AtomicUsize,
|
||||
wakers: Mutex<Option<Slab<Option<Waker>>>>,
|
||||
}
|
||||
|
||||
/// A weak reference to a [`Shared`] that can be upgraded much like an `Arc`.
|
||||
pub struct WeakShared<Fut: Future>(Weak<Inner<Fut>>);
|
||||
|
||||
impl<Fut: Future> Clone for WeakShared<Fut> {
|
||||
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<Fut: Future> Unpin for Shared<Fut> {}
|
||||
|
||||
impl<Fut: Future> fmt::Debug for Shared<Fut> {
|
||||
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<Fut: Future> fmt::Debug for Inner<Fut> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Inner").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> fmt::Debug for WeakShared<Fut> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("WeakShared").finish()
|
||||
}
|
||||
}
|
||||
|
||||
enum FutureOrOutput<Fut: Future> {
|
||||
Future(Fut),
|
||||
Output(Fut::Output),
|
||||
}
|
||||
|
||||
unsafe impl<Fut> Send for Inner<Fut>
|
||||
where
|
||||
Fut: Future + Send,
|
||||
Fut::Output: Send + Sync,
|
||||
{
|
||||
}
|
||||
|
||||
unsafe impl<Fut> Sync for Inner<Fut>
|
||||
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<Fut: Future> Shared<Fut> {
|
||||
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<Fut> Shared<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Clone,
|
||||
{
|
||||
/// 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<WeakShared<Fut>> {
|
||||
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.
|
||||
pub fn strong_count(&self) -> Option<usize> {
|
||||
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.
|
||||
pub fn weak_count(&self) -> Option<usize> {
|
||||
self.inner.as_ref().map(|arc| Arc::weak_count(arc))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Inner<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Clone,
|
||||
{
|
||||
/// 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!(),
|
||||
}
|
||||
}
|
||||
/// 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<Self>) -> 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<Fut> FusedFuture for Shared<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Clone,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.inner.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for Shared<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
Fut::Output: Clone,
|
||||
{
|
||||
type Output = Fut::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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>(&'a AtomicUsize);
|
||||
|
||||
impl Drop for Reset<'_> {
|
||||
fn drop(&mut self) {
|
||||
use std::thread;
|
||||
|
||||
if thread::panicking() {
|
||||
self.0.store(POISONED, SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _reset = Reset(&inner.notifier.state);
|
||||
|
||||
let output = {
|
||||
let future = unsafe {
|
||||
match &mut *inner.future_or_output.get() {
|
||||
FutureOrOutput::Future(fut) => Pin::new_unchecked(fut),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
match future.poll(&mut cx) {
|
||||
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<Fut> Clone for Shared<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self { inner: self.inner.clone(), waker_key: NULL_WAKER_KEY }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Drop for Shared<Fut>
|
||||
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<Self>) {
|
||||
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<Fut: Future> WeakShared<Fut> {
|
||||
/// 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<Shared<Fut>> {
|
||||
Some(Shared { inner: Some(self.0.upgrade()?), waker_key: NULL_WAKER_KEY })
|
||||
}
|
||||
}
|
||||
217
zeroidc/vendor/futures-util/src/future/join.rs
vendored
Normal file
217
zeroidc/vendor/futures-util/src/future/join.rs
vendored
Normal file
@@ -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<Self::Output> {
|
||||
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, <Fut1, Fut2>),
|
||||
|
||||
/// Future for the [`join3`] function.
|
||||
(Join3, <Fut1, Fut2, Fut3>),
|
||||
|
||||
/// Future for the [`join4`] function.
|
||||
(Join4, <Fut1, Fut2, Fut3, Fut4>),
|
||||
|
||||
/// Future for the [`join5`] function.
|
||||
(Join5, <Fut1, Fut2, Fut3, Fut4, Fut5>),
|
||||
}
|
||||
|
||||
/// 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<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> Join<Fut1, Fut2>
|
||||
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<Fut1, Fut2, Fut3>(
|
||||
future1: Fut1,
|
||||
future2: Fut2,
|
||||
future3: Fut3,
|
||||
) -> Join3<Fut1, Fut2, Fut3>
|
||||
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<Fut1, Fut2, Fut3, Fut4>(
|
||||
future1: Fut1,
|
||||
future2: Fut2,
|
||||
future3: Fut3,
|
||||
future4: Fut4,
|
||||
) -> Join4<Fut1, Fut2, Fut3, Fut4>
|
||||
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<Fut1, Fut2, Fut3, Fut4, Fut5>(
|
||||
future1: Fut1,
|
||||
future2: Fut2,
|
||||
future3: Fut3,
|
||||
future4: Fut4,
|
||||
future5: Fut5,
|
||||
) -> Join5<Fut1, Fut2, Fut3, Fut4, Fut5>
|
||||
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)
|
||||
}
|
||||
167
zeroidc/vendor/futures-util/src/future/join_all.rs
vendored
Normal file
167
zeroidc/vendor/futures-util/src/future/join_all.rs
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
//! 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};
|
||||
|
||||
fn iter_pin_mut<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> {
|
||||
// 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<F>
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
kind: JoinAllKind<F>,
|
||||
}
|
||||
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
const SMALL: usize = 30;
|
||||
|
||||
pub(crate) enum JoinAllKind<F>
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
Small {
|
||||
elems: Pin<Box<[MaybeDone<F>]>>,
|
||||
},
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
Big {
|
||||
fut: Collect<FuturesOrdered<F>, Vec<F::Output>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<F> fmt::Debug for JoinAll<F>
|
||||
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<T>` 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<I>(iter: I) -> JoinAll<I::Item>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Future,
|
||||
{
|
||||
#[cfg(futures_no_atomic_cas)]
|
||||
{
|
||||
let elems = iter.into_iter().map(MaybeDone::Future).collect::<Box<[_]>>().into();
|
||||
let kind = JoinAllKind::Small { elems };
|
||||
assert_future::<Vec<<I::Item as Future>::Output>, _>(JoinAll { kind })
|
||||
}
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let kind = match iter.size_hint().1 {
|
||||
None => JoinAllKind::Big { fut: iter.collect::<FuturesOrdered<_>>().collect() },
|
||||
Some(max) => {
|
||||
if max <= SMALL {
|
||||
let elems = iter.map(MaybeDone::Future).collect::<Box<[_]>>().into();
|
||||
JoinAllKind::Small { elems }
|
||||
} else {
|
||||
JoinAllKind::Big { fut: iter.collect::<FuturesOrdered<_>>().collect() }
|
||||
}
|
||||
}
|
||||
};
|
||||
assert_future::<Vec<<I::Item as Future>::Output>, _>(JoinAll { kind })
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Future for JoinAll<F>
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
type Output = Vec<F::Output>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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<F: Future> FromIterator<F> for JoinAll<F> {
|
||||
fn from_iter<T: IntoIterator<Item = F>>(iter: T) -> Self {
|
||||
join_all(iter)
|
||||
}
|
||||
}
|
||||
60
zeroidc/vendor/futures-util/src/future/lazy.rs
vendored
Normal file
60
zeroidc/vendor/futures-util/src/future/lazy.rs
vendored
Normal file
@@ -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> {
|
||||
f: Option<F>,
|
||||
}
|
||||
|
||||
// safe because we never generate `Pin<&mut F>`
|
||||
impl<F> Unpin for Lazy<F> {}
|
||||
|
||||
/// 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, R>(f: F) -> Lazy<F>
|
||||
where
|
||||
F: FnOnce(&mut Context<'_>) -> R,
|
||||
{
|
||||
assert_future::<R, _>(Lazy { f: Some(f) })
|
||||
}
|
||||
|
||||
impl<F, R> FusedFuture for Lazy<F>
|
||||
where
|
||||
F: FnOnce(&mut Context<'_>) -> R,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.f.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, R> Future for Lazy<F>
|
||||
where
|
||||
F: FnOnce(&mut Context<'_>) -> R,
|
||||
{
|
||||
type Output = R;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<R> {
|
||||
Poll::Ready((self.f.take().expect("Lazy polled after completion"))(cx))
|
||||
}
|
||||
}
|
||||
104
zeroidc/vendor/futures-util/src/future/maybe_done.rs
vendored
Normal file
104
zeroidc/vendor/futures-util/src/future/maybe_done.rs
vendored
Normal file
@@ -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<Fut: Future> {
|
||||
/// 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<Fut: Future + Unpin> Unpin for MaybeDone<Fut> {}
|
||||
|
||||
/// 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<Fut: Future>(future: Fut) -> MaybeDone<Fut> {
|
||||
assert_future::<(), _>(MaybeDone::Future(future))
|
||||
}
|
||||
|
||||
impl<Fut: Future> MaybeDone<Fut> {
|
||||
/// 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<Fut::Output> {
|
||||
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<Fut: Future> FusedFuture for MaybeDone<Fut> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Future(_) => false,
|
||||
Self::Done(_) | Self::Gone => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Future for MaybeDone<Fut> {
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
131
zeroidc/vendor/futures-util/src/future/mod.rs
vendored
Normal file
131
zeroidc/vendor/futures-util/src/future/mod.rs
vendored
Normal file
@@ -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<T, F>(future: F) -> F
|
||||
where
|
||||
F: Future<Output = T>,
|
||||
{
|
||||
future
|
||||
}
|
||||
64
zeroidc/vendor/futures-util/src/future/option.rs
vendored
Normal file
64
zeroidc/vendor/futures-util/src/future/option.rs
vendored
Normal file
@@ -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<F> {
|
||||
#[pin]
|
||||
inner: Option<F>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Default for OptionFuture<F> {
|
||||
fn default() -> Self {
|
||||
Self { inner: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Future> Future for OptionFuture<F> {
|
||||
type Output = Option<F::Output>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.project().inner.as_pin_mut() {
|
||||
Some(x) => x.poll(cx).map(Some),
|
||||
None => Poll::Ready(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FusedFuture> FusedFuture for OptionFuture<F> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
match &self.inner {
|
||||
Some(x) => x.is_terminated(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for OptionFuture<T> {
|
||||
fn from(option: Option<T>) -> Self {
|
||||
Self { inner: option }
|
||||
}
|
||||
}
|
||||
54
zeroidc/vendor/futures-util/src/future/pending.rs
vendored
Normal file
54
zeroidc/vendor/futures-util/src/future/pending.rs
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
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<T> {
|
||||
_data: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> FusedFuture for Pending<T> {
|
||||
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!();
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn pending<T>() -> Pending<T> {
|
||||
assert_future::<T, _>(Pending { _data: marker::PhantomData })
|
||||
}
|
||||
|
||||
impl<T> Future for Pending<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<T> {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Unpin for Pending<T> {}
|
||||
|
||||
impl<T> Clone for Pending<T> {
|
||||
fn clone(&self) -> Self {
|
||||
pending()
|
||||
}
|
||||
}
|
||||
58
zeroidc/vendor/futures-util/src/future/poll_fn.rs
vendored
Normal file
58
zeroidc/vendor/futures-util/src/future/poll_fn.rs
vendored
Normal file
@@ -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: F,
|
||||
}
|
||||
|
||||
impl<F> Unpin for PollFn<F> {}
|
||||
|
||||
/// 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<String> {
|
||||
/// 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<T, F>(f: F) -> PollFn<F>
|
||||
where
|
||||
F: FnMut(&mut Context<'_>) -> Poll<T>,
|
||||
{
|
||||
assert_future::<T, _>(PollFn { f })
|
||||
}
|
||||
|
||||
impl<F> fmt::Debug for PollFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PollFn").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F> Future for PollFn<F>
|
||||
where
|
||||
F: FnMut(&mut Context<'_>) -> Poll<T>,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
|
||||
(&mut self.f)(cx)
|
||||
}
|
||||
}
|
||||
126
zeroidc/vendor/futures-util/src/future/poll_immediate.rs
vendored
Normal file
126
zeroidc/vendor/futures-util/src/future/poll_immediate.rs
vendored
Normal file
@@ -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<T> {
|
||||
#[pin]
|
||||
future: Option<T>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F> Future for PollImmediate<F>
|
||||
where
|
||||
F: Future<Output = T>,
|
||||
{
|
||||
type Output = Option<T>;
|
||||
|
||||
#[inline]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<T>> {
|
||||
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<T: Future> FusedFuture for PollImmediate<T> {
|
||||
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<T, F> Stream for PollImmediate<F>
|
||||
where
|
||||
F: Future<Output = T>,
|
||||
{
|
||||
type Item = Poll<T>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
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::<i32>());
|
||||
/// 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: Future>(f: F) -> PollImmediate<F> {
|
||||
assert_future::<Option<F::Output>, PollImmediate<F>>(PollImmediate { future: Some(f) })
|
||||
}
|
||||
82
zeroidc/vendor/futures-util/src/future/ready.rs
vendored
Normal file
82
zeroidc/vendor/futures-util/src/future/ready.rs
vendored
Normal file
@@ -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<T>(Option<T>);
|
||||
|
||||
impl<T> Ready<T> {
|
||||
/// Unwraps the value from this immediately ready future.
|
||||
#[inline]
|
||||
pub fn into_inner(mut self) -> T {
|
||||
self.0.take().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Unpin for Ready<T> {}
|
||||
|
||||
impl<T> FusedFuture for Ready<T> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.0.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for Ready<T> {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
|
||||
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: T) -> Ready<T> {
|
||||
assert_future::<T, _>(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::<i32, i32>(1);
|
||||
/// assert_eq!(a.await, Ok(1));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn ok<T, E>(t: T) -> Ready<Result<T, E>> {
|
||||
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::<i32, i32>(1);
|
||||
/// assert_eq!(a.await, Err(1));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn err<T, E>(err: E) -> Ready<Result<T, E>> {
|
||||
Ready(Some(Err(err)))
|
||||
}
|
||||
124
zeroidc/vendor/futures-util/src/future/select.rs
vendored
Normal file
124
zeroidc/vendor/futures-util/src/future/select.rs
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
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<A, B> {
|
||||
inner: Option<(A, B)>,
|
||||
}
|
||||
|
||||
impl<A: Unpin, B: Unpin> Unpin for Select<A, B> {}
|
||||
|
||||
/// 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, B>(a: A, b: B) -> impl Future<Output=(A::Output, B::Output)>
|
||||
/// 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<A, B>(future1: A, future2: B) -> Select<A, B>
|
||||
where
|
||||
A: Future + Unpin,
|
||||
B: Future + Unpin,
|
||||
{
|
||||
assert_future::<Either<(A::Output, B), (B::Output, A)>, _>(Select {
|
||||
inner: Some((future1, future2)),
|
||||
})
|
||||
}
|
||||
|
||||
impl<A, B> Future for Select<A, B>
|
||||
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<Self::Output> {
|
||||
let (mut a, mut b) = self.inner.take().expect("cannot poll Select twice");
|
||||
match a.poll_unpin(cx) {
|
||||
Poll::Ready(x) => Poll::Ready(Either::Left((x, b))),
|
||||
Poll::Pending => match b.poll_unpin(cx) {
|
||||
Poll::Ready(x) => Poll::Ready(Either::Right((x, a))),
|
||||
Poll::Pending => {
|
||||
self.inner = Some((a, b));
|
||||
Poll::Pending
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> FusedFuture for Select<A, B>
|
||||
where
|
||||
A: Future + Unpin,
|
||||
B: Future + Unpin,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.inner.is_none()
|
||||
}
|
||||
}
|
||||
74
zeroidc/vendor/futures-util/src/future/select_all.rs
vendored
Normal file
74
zeroidc/vendor/futures-util/src/future/select_all.rs
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
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<Fut> {
|
||||
inner: Vec<Fut>,
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> Unpin for SelectAll<Fut> {}
|
||||
|
||||
/// 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<I>(iter: I) -> SelectAll<I::Item>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Future + Unpin,
|
||||
{
|
||||
let ret = SelectAll { inner: iter.into_iter().collect() };
|
||||
assert!(!ret.inner.is_empty());
|
||||
assert_future::<(<I::Item as Future>::Output, usize, Vec<I::Item>), _>(ret)
|
||||
}
|
||||
|
||||
impl<Fut> SelectAll<Fut> {
|
||||
/// Consumes this combinator, returning the underlying futures.
|
||||
pub fn into_inner(self) -> Vec<Fut> {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future + Unpin> Future for SelectAll<Fut> {
|
||||
type Output = (Fut::Output, usize, Vec<Fut>);
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let item = self.inner.iter_mut().enumerate().find_map(|(i, f)| match f.poll_unpin(cx) {
|
||||
Poll::Pending => None,
|
||||
Poll::Ready(e) => Some((i, e)),
|
||||
});
|
||||
match item {
|
||||
Some((idx, res)) => {
|
||||
let _ = self.inner.swap_remove(idx);
|
||||
let rest = mem::replace(&mut self.inner, Vec::new());
|
||||
Poll::Ready((res, idx, rest))
|
||||
}
|
||||
None => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future + Unpin> FromIterator<Fut> for SelectAll<Fut> {
|
||||
fn from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self {
|
||||
select_all(iter)
|
||||
}
|
||||
}
|
||||
85
zeroidc/vendor/futures-util/src/future/select_ok.rs
vendored
Normal file
85
zeroidc/vendor/futures-util/src/future/select_ok.rs
vendored
Normal file
@@ -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<Fut> {
|
||||
inner: Vec<Fut>,
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> Unpin for SelectOk<Fut> {}
|
||||
|
||||
/// 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<I>(iter: I) -> SelectOk<I::Item>
|
||||
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<(<I::Item as TryFuture>::Ok, Vec<I::Item>), <I::Item as TryFuture>::Error>,
|
||||
_,
|
||||
>(ret)
|
||||
}
|
||||
|
||||
impl<Fut: TryFuture + Unpin> Future for SelectOk<Fut> {
|
||||
type Output = Result<(Fut::Ok, Vec<Fut>), Fut::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// 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::replace(&mut self.inner, Vec::new());
|
||||
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<Fut: TryFuture + Unpin> FromIterator<Fut> for SelectOk<Fut> {
|
||||
fn from_iter<T: IntoIterator<Item = Fut>>(iter: T) -> Self {
|
||||
select_ok(iter)
|
||||
}
|
||||
}
|
||||
36
zeroidc/vendor/futures-util/src/future/try_future/into_future.rs
vendored
Normal file
36
zeroidc/vendor/futures-util/src/future/try_future/into_future.rs
vendored
Normal file
@@ -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<Fut> {
|
||||
#[pin]
|
||||
future: Fut,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> IntoFuture<Fut> {
|
||||
#[inline]
|
||||
pub(crate) fn new(future: Fut) -> Self {
|
||||
Self { future }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: TryFuture + FusedFuture> FusedFuture for IntoFuture<Fut> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.future.is_terminated()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: TryFuture> Future for IntoFuture<Fut> {
|
||||
type Output = Result<Fut::Ok, Fut::Error>;
|
||||
|
||||
#[inline]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.project().future.try_poll(cx)
|
||||
}
|
||||
}
|
||||
619
zeroidc/vendor/futures-util/src/future/try_future/mod.rs
vendored
Normal file
619
zeroidc/vendor/futures-util/src/future/try_future/mod.rs
vendored
Normal file
@@ -0,0 +1,619 @@
|
||||
//! 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<Fut1, Fut2>(
|
||||
try_flatten::TryFlatten<Fut1, Fut2>
|
||||
): 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<Fut1, Fut2>(
|
||||
try_flatten_err::TryFlattenErr<Fut1, Fut2>
|
||||
): 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<Fut>(
|
||||
try_flatten::TryFlatten<Fut, Fut::Ok>
|
||||
): 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<Fut, Si>(
|
||||
try_flatten::TryFlatten<Fut, Si>
|
||||
): Debug + Sink + Stream + FusedStream + New[|x: Fut| try_flatten::TryFlatten::new(x)]
|
||||
);
|
||||
|
||||
delegate_all!(
|
||||
/// Future for the [`and_then`](TryFutureExt::and_then) method.
|
||||
AndThen<Fut1, Fut2, F>(
|
||||
TryFlatten<MapOk<Fut1, F>, 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<Fut1, Fut2, F>(
|
||||
TryFlattenErr<MapErr<Fut1, F>, 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<Fut, E>(
|
||||
MapErr<Fut, IntoFn<E>>
|
||||
): Debug + Future + FusedFuture + New[|x: Fut| MapErr::new(x, into_fn())]
|
||||
);
|
||||
|
||||
delegate_all!(
|
||||
/// Future for the [`ok_into`](TryFutureExt::ok_into) method.
|
||||
OkInto<Fut, E>(
|
||||
MapOk<Fut, IntoFn<E>>
|
||||
): Debug + Future + FusedFuture + New[|x: Fut| MapOk::new(x, into_fn())]
|
||||
);
|
||||
|
||||
delegate_all!(
|
||||
/// Future for the [`inspect_ok`](super::TryFutureExt::inspect_ok) method.
|
||||
InspectOk<Fut, F>(
|
||||
Inspect<IntoFuture<Fut>, InspectOkFn<F>>
|
||||
): 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<Fut, F>(
|
||||
Inspect<IntoFuture<Fut>, InspectErrFn<F>>
|
||||
): 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<Fut, F>(
|
||||
Map<IntoFuture<Fut>, MapOkFn<F>>
|
||||
): 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<Fut, F>(
|
||||
Map<IntoFuture<Fut>, MapErrFn<F>>
|
||||
): 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<Fut, F, G>(
|
||||
Map<IntoFuture<Fut>, MapOkOrElseFn<F, G>>
|
||||
): 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<Fut, F>(
|
||||
Map<IntoFuture<Fut>, UnwrapOrElseFn<F>>
|
||||
): Debug + Future + FusedFuture + New[|x: Fut, f: F| Map::new(IntoFuture::new(x), unwrap_or_else_fn(f))]
|
||||
);
|
||||
|
||||
impl<Fut: ?Sized + TryFuture> 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<Output = Result<
|
||||
/// impl Sink<T, Error = E>,
|
||||
/// E,
|
||||
/// >> { // ... }
|
||||
/// # let (tx, _rx) = mpsc::unbounded::<i32>();
|
||||
/// # futures::future::ready(Ok(tx))
|
||||
/// # }
|
||||
/// fn take_sink(sink: impl Sink<T, Error = E>) { /* ... */ }
|
||||
///
|
||||
/// let fut = make_sink_async();
|
||||
/// take_sink(fut.flatten_sink())
|
||||
/// ```
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
fn flatten_sink<Item>(self) -> FlattenSink<Self, Self::Ok>
|
||||
where
|
||||
Self::Ok: Sink<Item, Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
crate::sink::assert_sink::<Item, Self::Error, _>(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::<i32, i32>(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::<i32, i32>(1) };
|
||||
/// let future = future.map_ok(|x| x + 3);
|
||||
/// assert_eq!(future.await, Err(1));
|
||||
/// # });
|
||||
/// ```
|
||||
fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
|
||||
where
|
||||
F: FnOnce(Self::Ok) -> T,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<T, Self::Error>, _>(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::<i32, i32>(5) };
|
||||
/// let future = future.map_ok_or_else(|x| x * 2, |x| x + 3);
|
||||
/// assert_eq!(future.await, 8);
|
||||
///
|
||||
/// let future = async { Err::<i32, i32>(5) };
|
||||
/// let future = future.map_ok_or_else(|x| x * 2, |x| x + 3);
|
||||
/// assert_eq!(future.await, 10);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
fn map_ok_or_else<T, E, F>(self, e: E, f: F) -> MapOkOrElse<Self, F, E>
|
||||
where
|
||||
F: FnOnce(Self::Ok) -> T,
|
||||
E: FnOnce(Self::Error) -> T,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<T, _>(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::<i32, i32>(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::<i32, i32>(1) };
|
||||
/// let future = future.map_err(|x| x + 3);
|
||||
/// assert_eq!(future.await, Ok(1));
|
||||
/// # });
|
||||
/// ```
|
||||
fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
|
||||
where
|
||||
F: FnOnce(Self::Error) -> E,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Self::Ok, E>, _>(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::<i32>();
|
||||
/// # });
|
||||
/// ```
|
||||
fn err_into<E>(self) -> ErrInto<Self, E>
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Error: Into<E>,
|
||||
{
|
||||
assert_future::<Result<Self::Ok, E>, _>(ErrInto::new(self))
|
||||
}
|
||||
|
||||
/// Maps this future's [`Ok`](TryFuture::Ok) to a new type
|
||||
/// using the [`Into`](std::convert::Into) trait.
|
||||
fn ok_into<U>(self) -> OkInto<Self, U>
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Ok: Into<U>,
|
||||
{
|
||||
assert_future::<Result<U, Self::Error>, _>(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::<i32, i32>(1) };
|
||||
/// let future = future.and_then(|x| async move { Ok::<i32, i32>(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::<i32, i32>(1) };
|
||||
/// let future = future.and_then(|x| async move { Err::<i32, i32>(x + 3) });
|
||||
/// assert_eq!(future.await, Err(1));
|
||||
/// # });
|
||||
/// ```
|
||||
fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
|
||||
where
|
||||
F: FnOnce(Self::Ok) -> Fut,
|
||||
Fut: TryFuture<Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Fut::Ok, Fut::Error>, _>(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::<i32, i32>(1) };
|
||||
/// let future = future.or_else(|x| async move { Err::<i32, i32>(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::<i32, i32>(1) };
|
||||
/// let future = future.or_else(|x| async move { Ok::<i32, i32>(x + 3) });
|
||||
/// assert_eq!(future.await, Ok(1));
|
||||
/// # });
|
||||
/// ```
|
||||
fn or_else<Fut, F>(self, f: F) -> OrElse<Self, Fut, F>
|
||||
where
|
||||
F: FnOnce(Self::Error) -> Fut,
|
||||
Fut: TryFuture<Ok = Self::Ok>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Fut::Ok, Fut::Error>, _>(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<F>(self, f: F) -> InspectOk<Self, F>
|
||||
where
|
||||
F: FnOnce(&Self::Ok),
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Self::Ok, Self::Error>, _>(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<F>(self, f: F) -> InspectErr<Self, F>
|
||||
where
|
||||
F: FnOnce(&Self::Error),
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Self::Ok, Self::Error>, _>(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<Self, Self::Ok>
|
||||
where
|
||||
Self::Ok: TryFuture<Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<<Self::Ok as TryFuture>::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::<Vec<_>>().await;
|
||||
/// assert_eq!(list, Ok(vec![17, 18, 19]));
|
||||
/// # });
|
||||
/// ```
|
||||
fn try_flatten_stream(self) -> TryFlattenStream<Self>
|
||||
where
|
||||
Self::Ok: TryStream<Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_stream::<Result<<Self::Ok as TryStream>::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<F>(self, f: F) -> UnwrapOrElse<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(Self::Error) -> Self::Ok,
|
||||
{
|
||||
assert_future::<Self::Ok, _>(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<Self>
|
||||
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<Ok = T, Error = E> { // ... }
|
||||
/// # async { Ok::<i32, ()>(1) }
|
||||
/// # }
|
||||
/// fn take_future(future: impl Future<Output = Result<T, E>>) { /* ... */ }
|
||||
///
|
||||
/// take_future(make_try_future().into_future());
|
||||
/// ```
|
||||
fn into_future(self) -> IntoFuture<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_future::<Result<Self::Ok, Self::Error>, _>(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<Result<Self::Ok, Self::Error>>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
Pin::new(self).try_poll(cx)
|
||||
}
|
||||
}
|
||||
162
zeroidc/vendor/futures-util/src/future/try_future/try_flatten.rs
vendored
Normal file
162
zeroidc/vendor/futures-util/src/future/try_future/try_flatten.rs
vendored
Normal file
@@ -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<Fut1, Fut2> {
|
||||
First { #[pin] f: Fut1 },
|
||||
Second { #[pin] f: Fut2 },
|
||||
Empty,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut1, Fut2> TryFlatten<Fut1, Fut2> {
|
||||
pub(crate) fn new(future: Fut1) -> Self {
|
||||
Self::First { f: future }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> FusedFuture for TryFlatten<Fut, Fut::Ok>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Ok: TryFuture<Error = Fut::Error>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Empty => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for TryFlatten<Fut, Fut::Ok>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Ok: TryFuture<Error = Fut::Error>,
|
||||
{
|
||||
type Output = Result<<Fut::Ok as TryFuture>::Ok, Fut::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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<Fut> FusedStream for TryFlatten<Fut, Fut::Ok>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Ok: TryStream<Error = Fut::Error>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Empty => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Stream for TryFlatten<Fut, Fut::Ok>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Ok: TryStream<Error = Fut::Error>,
|
||||
{
|
||||
type Item = Result<<Fut::Ok as TryStream>::Ok, Fut::Error>;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
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<Fut, Item> Sink<Item> for TryFlatten<Fut, Fut::Ok>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Ok: Sink<Item, Error = Fut::Error>,
|
||||
{
|
||||
type Error = Fut::Error;
|
||||
|
||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
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<Result<(), Self::Error>> {
|
||||
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<Result<(), Self::Error>> {
|
||||
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
|
||||
}
|
||||
}
|
||||
62
zeroidc/vendor/futures-util/src/future/try_future/try_flatten_err.rs
vendored
Normal file
62
zeroidc/vendor/futures-util/src/future/try_future/try_flatten_err.rs
vendored
Normal file
@@ -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<Fut1, Fut2> {
|
||||
First { #[pin] f: Fut1 },
|
||||
Second { #[pin] f: Fut2 },
|
||||
Empty,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut1, Fut2> TryFlattenErr<Fut1, Fut2> {
|
||||
pub(crate) fn new(future: Fut1) -> Self {
|
||||
Self::First { f: future }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> FusedFuture for TryFlattenErr<Fut, Fut::Error>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Error: TryFuture<Ok = Fut::Ok>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Empty => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for TryFlattenErr<Fut, Fut::Error>
|
||||
where
|
||||
Fut: TryFuture,
|
||||
Fut::Error: TryFuture<Ok = Fut::Ok>,
|
||||
{
|
||||
type Output = Result<Fut::Ok, <Fut::Error as TryFuture>::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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"),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
256
zeroidc/vendor/futures-util/src/future/try_join.rs
vendored
Normal file
256
zeroidc/vendor/futures-util/src/future/try_join.rs
vendored
Normal file
@@ -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, <Fut1, $($Fut:ident),*>),
|
||||
)*) => ($(
|
||||
pin_project! {
|
||||
$(#[$doc])*
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct $Join<Fut1: TryFuture, $($Fut: TryFuture),*> {
|
||||
#[pin] Fut1: TryMaybeDone<Fut1>,
|
||||
$(#[pin] $Fut: TryMaybeDone<$Fut>,)*
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut1, $($Fut),*> fmt::Debug for $Join<Fut1, $($Fut),*>
|
||||
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<Fut1, $($Fut),*> $Join<Fut1, $($Fut),*>
|
||||
where
|
||||
Fut1: TryFuture,
|
||||
$(
|
||||
$Fut: TryFuture<Error=Fut1::Error>
|
||||
),*
|
||||
{
|
||||
fn new(Fut1: Fut1, $($Fut: $Fut),*) -> Self {
|
||||
Self {
|
||||
Fut1: try_maybe_done(Fut1),
|
||||
$($Fut: try_maybe_done($Fut)),*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut1, $($Fut),*> Future for $Join<Fut1, $($Fut),*>
|
||||
where
|
||||
Fut1: TryFuture,
|
||||
$(
|
||||
$Fut: TryFuture<Error=Fut1::Error>
|
||||
),*
|
||||
{
|
||||
type Output = Result<(Fut1::Ok, $($Fut::Ok),*), Fut1::Error>;
|
||||
|
||||
fn poll(
|
||||
self: Pin<&mut Self>, cx: &mut Context<'_>
|
||||
) -> Poll<Self::Output> {
|
||||
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, <Fut1, Fut2>),
|
||||
|
||||
/// Future for the [`try_join3`] function.
|
||||
(TryJoin3, <Fut1, Fut2, Fut3>),
|
||||
|
||||
/// Future for the [`try_join4`] function.
|
||||
(TryJoin4, <Fut1, Fut2, Fut3, Fut4>),
|
||||
|
||||
/// Future for the [`try_join5`] function.
|
||||
(TryJoin5, <Fut1, Fut2, Fut3, Fut4, Fut5>),
|
||||
}
|
||||
|
||||
/// 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::<i32, i32>(1));
|
||||
/// let b = future::ready(Ok::<i32, i32>(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::<i32, i32>(1));
|
||||
/// let b = future::ready(Err::<i32, i32>(2));
|
||||
/// let pair = future::try_join(a, b);
|
||||
///
|
||||
/// assert_eq!(pair.await, Err(2));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn try_join<Fut1, Fut2>(future1: Fut1, future2: Fut2) -> TryJoin<Fut1, Fut2>
|
||||
where
|
||||
Fut1: TryFuture,
|
||||
Fut2: TryFuture<Error = Fut1::Error>,
|
||||
{
|
||||
assert_future::<Result<(Fut1::Ok, Fut2::Ok), Fut1::Error>, _>(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::<i32, i32>(1));
|
||||
/// let b = future::ready(Ok::<i32, i32>(2));
|
||||
/// let c = future::ready(Ok::<i32, i32>(3));
|
||||
/// let tuple = future::try_join3(a, b, c);
|
||||
///
|
||||
/// assert_eq!(tuple.await, Ok((1, 2, 3)));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn try_join3<Fut1, Fut2, Fut3>(
|
||||
future1: Fut1,
|
||||
future2: Fut2,
|
||||
future3: Fut3,
|
||||
) -> TryJoin3<Fut1, Fut2, Fut3>
|
||||
where
|
||||
Fut1: TryFuture,
|
||||
Fut2: TryFuture<Error = Fut1::Error>,
|
||||
Fut3: TryFuture<Error = Fut1::Error>,
|
||||
{
|
||||
assert_future::<Result<(Fut1::Ok, Fut2::Ok, Fut3::Ok), Fut1::Error>, _>(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::<i32, i32>(1));
|
||||
/// let b = future::ready(Ok::<i32, i32>(2));
|
||||
/// let c = future::ready(Ok::<i32, i32>(3));
|
||||
/// let d = future::ready(Ok::<i32, i32>(4));
|
||||
/// let tuple = future::try_join4(a, b, c, d);
|
||||
///
|
||||
/// assert_eq!(tuple.await, Ok((1, 2, 3, 4)));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn try_join4<Fut1, Fut2, Fut3, Fut4>(
|
||||
future1: Fut1,
|
||||
future2: Fut2,
|
||||
future3: Fut3,
|
||||
future4: Fut4,
|
||||
) -> TryJoin4<Fut1, Fut2, Fut3, Fut4>
|
||||
where
|
||||
Fut1: TryFuture,
|
||||
Fut2: TryFuture<Error = Fut1::Error>,
|
||||
Fut3: TryFuture<Error = Fut1::Error>,
|
||||
Fut4: TryFuture<Error = Fut1::Error>,
|
||||
{
|
||||
assert_future::<Result<(Fut1::Ok, Fut2::Ok, Fut3::Ok, Fut4::Ok), Fut1::Error>, _>(
|
||||
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::<i32, i32>(1));
|
||||
/// let b = future::ready(Ok::<i32, i32>(2));
|
||||
/// let c = future::ready(Ok::<i32, i32>(3));
|
||||
/// let d = future::ready(Ok::<i32, i32>(4));
|
||||
/// let e = future::ready(Ok::<i32, i32>(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<Fut1, Fut2, Fut3, Fut4, Fut5>(
|
||||
future1: Fut1,
|
||||
future2: Fut2,
|
||||
future3: Fut3,
|
||||
future4: Fut4,
|
||||
future5: Fut5,
|
||||
) -> TryJoin5<Fut1, Fut2, Fut3, Fut4, Fut5>
|
||||
where
|
||||
Fut1: TryFuture,
|
||||
Fut2: TryFuture<Error = Fut1::Error>,
|
||||
Fut3: TryFuture<Error = Fut1::Error>,
|
||||
Fut4: TryFuture<Error = Fut1::Error>,
|
||||
Fut5: TryFuture<Error = Fut1::Error>,
|
||||
{
|
||||
assert_future::<Result<(Fut1::Ok, Fut2::Ok, Fut3::Ok, Fut4::Ok, Fut5::Ok), Fut1::Error>, _>(
|
||||
TryJoin5::new(future1, future2, future3, future4, future5),
|
||||
)
|
||||
}
|
||||
137
zeroidc/vendor/futures-util/src/future/try_join_all.rs
vendored
Normal file
137
zeroidc/vendor/futures-util/src/future/try_join_all.rs
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
//! 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, TryFuture, TryMaybeDone};
|
||||
|
||||
fn iter_pin_mut<T>(slice: Pin<&mut [T]>) -> impl Iterator<Item = Pin<&mut T>> {
|
||||
// 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) })
|
||||
}
|
||||
|
||||
enum FinalState<E = ()> {
|
||||
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<F>
|
||||
where
|
||||
F: TryFuture,
|
||||
{
|
||||
elems: Pin<Box<[TryMaybeDone<F>]>>,
|
||||
}
|
||||
|
||||
impl<F> fmt::Debug for TryJoinAll<F>
|
||||
where
|
||||
F: TryFuture + fmt::Debug,
|
||||
F::Ok: fmt::Debug,
|
||||
F::Error: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("TryJoinAll").field("elems", &self.elems).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<T>` 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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future::{self, try_join_all};
|
||||
///
|
||||
/// let futures = vec![
|
||||
/// future::ok::<u32, u32>(1),
|
||||
/// future::ok::<u32, u32>(2),
|
||||
/// future::ok::<u32, u32>(3),
|
||||
/// ];
|
||||
///
|
||||
/// assert_eq!(try_join_all(futures).await, Ok(vec![1, 2, 3]));
|
||||
///
|
||||
/// let futures = vec![
|
||||
/// future::ok::<u32, u32>(1),
|
||||
/// future::err::<u32, u32>(2),
|
||||
/// future::ok::<u32, u32>(3),
|
||||
/// ];
|
||||
///
|
||||
/// assert_eq!(try_join_all(futures).await, Err(2));
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn try_join_all<I>(i: I) -> TryJoinAll<I::Item>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: TryFuture,
|
||||
{
|
||||
let elems: Box<[_]> = i.into_iter().map(TryMaybeDone::Future).collect();
|
||||
assert_future::<Result<Vec<<I::Item as TryFuture>::Ok>, <I::Item as TryFuture>::Error>, _>(
|
||||
TryJoinAll { elems: elems.into() },
|
||||
)
|
||||
}
|
||||
|
||||
impl<F> Future for TryJoinAll<F>
|
||||
where
|
||||
F: TryFuture,
|
||||
{
|
||||
type Output = Result<Vec<F::Ok>, F::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut state = FinalState::AllDone;
|
||||
|
||||
for elem in iter_pin_mut(self.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(&mut self.elems, Box::pin([]));
|
||||
let results =
|
||||
iter_pin_mut(elems.as_mut()).map(|e| e.take_output().unwrap()).collect();
|
||||
Poll::Ready(Ok(results))
|
||||
}
|
||||
FinalState::Error(e) => {
|
||||
let _ = mem::replace(&mut self.elems, Box::pin([]));
|
||||
Poll::Ready(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: TryFuture> FromIterator<F> for TryJoinAll<F> {
|
||||
fn from_iter<T: IntoIterator<Item = F>>(iter: T) -> Self {
|
||||
try_join_all(iter)
|
||||
}
|
||||
}
|
||||
92
zeroidc/vendor/futures-util/src/future/try_maybe_done.rs
vendored
Normal file
92
zeroidc/vendor/futures-util/src/future/try_maybe_done.rs
vendored
Normal file
@@ -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<Fut: TryFuture> {
|
||||
/// 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<Fut: TryFuture + Unpin> Unpin for TryMaybeDone<Fut> {}
|
||||
|
||||
/// Wraps a future into a `TryMaybeDone`
|
||||
pub fn try_maybe_done<Fut: TryFuture>(future: Fut) -> TryMaybeDone<Fut> {
|
||||
assert_future::<Result<(), Fut::Error>, _>(TryMaybeDone::Future(future))
|
||||
}
|
||||
|
||||
impl<Fut: TryFuture> TryMaybeDone<Fut> {
|
||||
/// 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<Fut::Ok> {
|
||||
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<Fut: TryFuture> FusedFuture for TryMaybeDone<Fut> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::Future(_) => false,
|
||||
Self::Done(_) | Self::Gone => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: TryFuture> Future for TryMaybeDone<Fut> {
|
||||
type Output = Result<(), Fut::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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(()))
|
||||
}
|
||||
}
|
||||
84
zeroidc/vendor/futures-util/src/future/try_select.rs
vendored
Normal file
84
zeroidc/vendor/futures-util/src/future/try_select.rs
vendored
Normal file
@@ -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<A, B> {
|
||||
inner: Option<(A, B)>,
|
||||
}
|
||||
|
||||
impl<A: Unpin, B: Unpin> Unpin for TrySelect<A, B> {}
|
||||
|
||||
/// 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, B, E>(a: A, b: B) -> impl TryFuture<Ok=(A::Ok, B::Ok), Error=E>
|
||||
/// where A: TryFuture<Error = E> + Unpin + 'static,
|
||||
/// B: TryFuture<Error = E> + Unpin + 'static,
|
||||
/// E: 'static,
|
||||
/// {
|
||||
/// future::try_select(a, b).then(|res| -> Box<dyn Future<Output = Result<_, _>> + 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<A, B>(future1: A, future2: B) -> TrySelect<A, B>
|
||||
where
|
||||
A: TryFuture + Unpin,
|
||||
B: TryFuture + Unpin,
|
||||
{
|
||||
super::assert_future::<
|
||||
Result<Either<(A::Ok, B), (B::Ok, A)>, Either<(A::Error, B), (B::Error, A)>>,
|
||||
_,
|
||||
>(TrySelect { inner: Some((future1, future2)) })
|
||||
}
|
||||
|
||||
impl<A: Unpin, B: Unpin> Future for TrySelect<A, B>
|
||||
where
|
||||
A: TryFuture,
|
||||
B: TryFuture,
|
||||
{
|
||||
#[allow(clippy::type_complexity)]
|
||||
type Output = Result<Either<(A::Ok, B), (B::Ok, A)>, Either<(A::Error, B), (B::Error, A)>>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
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
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user