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:
185
zeroidc/vendor/futures-util/src/abortable.rs
vendored
Normal file
185
zeroidc/vendor/futures-util/src/abortable.rs
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
use crate::task::AtomicWaker;
|
||||
use alloc::sync::Arc;
|
||||
use core::fmt;
|
||||
use core::pin::Pin;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_core::Stream;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// A future/stream which can be remotely short-circuited using an `AbortHandle`.
|
||||
#[derive(Debug, Clone)]
|
||||
#[must_use = "futures/streams do nothing unless you poll them"]
|
||||
pub struct Abortable<T> {
|
||||
#[pin]
|
||||
task: T,
|
||||
inner: Arc<AbortInner>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Abortable<T> {
|
||||
/// Creates a new `Abortable` future/stream using an existing `AbortRegistration`.
|
||||
/// `AbortRegistration`s can be acquired through `AbortHandle::new`.
|
||||
///
|
||||
/// When `abort` is called on the handle tied to `reg` or if `abort` has
|
||||
/// already been called, the future/stream will complete immediately without making
|
||||
/// any further progress.
|
||||
///
|
||||
/// # Examples:
|
||||
///
|
||||
/// Usage with futures:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future::{Abortable, AbortHandle, Aborted};
|
||||
///
|
||||
/// let (abort_handle, abort_registration) = AbortHandle::new_pair();
|
||||
/// let future = Abortable::new(async { 2 }, abort_registration);
|
||||
/// abort_handle.abort();
|
||||
/// assert_eq!(future.await, Err(Aborted));
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// Usage with streams:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// # use futures::future::{Abortable, AbortHandle};
|
||||
/// # use futures::stream::{self, StreamExt};
|
||||
///
|
||||
/// let (abort_handle, abort_registration) = AbortHandle::new_pair();
|
||||
/// let mut stream = Abortable::new(stream::iter(vec![1, 2, 3]), abort_registration);
|
||||
/// abort_handle.abort();
|
||||
/// assert_eq!(stream.next().await, None);
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn new(task: T, reg: AbortRegistration) -> Self {
|
||||
Self { task, inner: reg.inner }
|
||||
}
|
||||
|
||||
/// Checks whether the task has been aborted. Note that all this
|
||||
/// method indicates is whether [`AbortHandle::abort`] was *called*.
|
||||
/// This means that it will return `true` even if:
|
||||
/// * `abort` was called after the task had completed.
|
||||
/// * `abort` was called while the task was being polled - the task may still be running and
|
||||
/// will not be stopped until `poll` returns.
|
||||
pub fn is_aborted(&self) -> bool {
|
||||
self.inner.aborted.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
/// A registration handle for an `Abortable` task.
|
||||
/// Values of this type can be acquired from `AbortHandle::new` and are used
|
||||
/// in calls to `Abortable::new`.
|
||||
#[derive(Debug)]
|
||||
pub struct AbortRegistration {
|
||||
inner: Arc<AbortInner>,
|
||||
}
|
||||
|
||||
/// A handle to an `Abortable` task.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AbortHandle {
|
||||
inner: Arc<AbortInner>,
|
||||
}
|
||||
|
||||
impl AbortHandle {
|
||||
/// Creates an (`AbortHandle`, `AbortRegistration`) pair which can be used
|
||||
/// to abort a running future or stream.
|
||||
///
|
||||
/// This function is usually paired with a call to [`Abortable::new`].
|
||||
pub fn new_pair() -> (Self, AbortRegistration) {
|
||||
let inner =
|
||||
Arc::new(AbortInner { waker: AtomicWaker::new(), aborted: AtomicBool::new(false) });
|
||||
|
||||
(Self { inner: inner.clone() }, AbortRegistration { inner })
|
||||
}
|
||||
}
|
||||
|
||||
// Inner type storing the waker to awaken and a bool indicating that it
|
||||
// should be aborted.
|
||||
#[derive(Debug)]
|
||||
struct AbortInner {
|
||||
waker: AtomicWaker,
|
||||
aborted: AtomicBool,
|
||||
}
|
||||
|
||||
/// Indicator that the `Abortable` task was aborted.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Aborted;
|
||||
|
||||
impl fmt::Display for Aborted {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "`Abortable` future has been aborted")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for Aborted {}
|
||||
|
||||
impl<T> Abortable<T> {
|
||||
fn try_poll<I>(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
poll: impl Fn(Pin<&mut T>, &mut Context<'_>) -> Poll<I>,
|
||||
) -> Poll<Result<I, Aborted>> {
|
||||
// Check if the task has been aborted
|
||||
if self.is_aborted() {
|
||||
return Poll::Ready(Err(Aborted));
|
||||
}
|
||||
|
||||
// attempt to complete the task
|
||||
if let Poll::Ready(x) = poll(self.as_mut().project().task, cx) {
|
||||
return Poll::Ready(Ok(x));
|
||||
}
|
||||
|
||||
// Register to receive a wakeup if the task is aborted in the future
|
||||
self.inner.waker.register(cx.waker());
|
||||
|
||||
// Check to see if the task was aborted between the first check and
|
||||
// registration.
|
||||
// Checking with `is_aborted` which uses `Relaxed` is sufficient because
|
||||
// `register` introduces an `AcqRel` barrier.
|
||||
if self.is_aborted() {
|
||||
return Poll::Ready(Err(Aborted));
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future for Abortable<Fut>
|
||||
where
|
||||
Fut: Future,
|
||||
{
|
||||
type Output = Result<Fut::Output, Aborted>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.try_poll(cx, |fut, cx| fut.poll(cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<St> Stream for Abortable<St>
|
||||
where
|
||||
St: Stream,
|
||||
{
|
||||
type Item = St::Item;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
self.try_poll(cx, |stream, cx| stream.poll_next(cx)).map(Result::ok).map(Option::flatten)
|
||||
}
|
||||
}
|
||||
|
||||
impl AbortHandle {
|
||||
/// Abort the `Abortable` stream/future associated with this handle.
|
||||
///
|
||||
/// Notifies the Abortable task associated with this handle that it
|
||||
/// should abort. Note that if the task is currently being polled on
|
||||
/// another thread, it will not immediately stop running. Instead, it will
|
||||
/// continue to run until its poll method returns.
|
||||
pub fn abort(&self) {
|
||||
self.inner.aborted.store(true, Ordering::Relaxed);
|
||||
self.inner.waker.wake();
|
||||
}
|
||||
}
|
||||
110
zeroidc/vendor/futures-util/src/async_await/join_mod.rs
vendored
Normal file
110
zeroidc/vendor/futures-util/src/async_await/join_mod.rs
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
//! The `join` macro.
|
||||
|
||||
macro_rules! document_join_macro {
|
||||
($join:item $try_join:item) => {
|
||||
/// Polls multiple futures simultaneously, returning a tuple
|
||||
/// of all results once complete.
|
||||
///
|
||||
/// While `join!(a, b)` is similar to `(a.await, b.await)`,
|
||||
/// `join!` polls both futures concurrently and therefore is more efficient.
|
||||
///
|
||||
/// This macro is only usable inside of async functions, closures, and blocks.
|
||||
/// It is also gated behind the `async-await` feature of this library, which is
|
||||
/// activated by default.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::join;
|
||||
///
|
||||
/// let a = async { 1 };
|
||||
/// let b = async { 2 };
|
||||
/// assert_eq!(join!(a, b), (1, 2));
|
||||
///
|
||||
/// // `join!` is variadic, so you can pass any number of futures
|
||||
/// let c = async { 3 };
|
||||
/// let d = async { 4 };
|
||||
/// let e = async { 5 };
|
||||
/// assert_eq!(join!(c, d, e), (3, 4, 5));
|
||||
/// # });
|
||||
/// ```
|
||||
$join
|
||||
|
||||
/// Polls multiple futures simultaneously, resolving to a [`Result`] containing
|
||||
/// either a tuple of the successful outputs or an error.
|
||||
///
|
||||
/// `try_join!` is similar to [`join!`], but completes immediately if any of
|
||||
/// the futures return an error.
|
||||
///
|
||||
/// This macro is only usable inside of async functions, closures, and blocks.
|
||||
/// It is also gated behind the `async-await` feature of this library, which is
|
||||
/// activated by default.
|
||||
///
|
||||
/// # 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::try_join;
|
||||
///
|
||||
/// let a = async { Ok::<i32, i32>(1) };
|
||||
/// let b = async { Ok::<i32, i32>(2) };
|
||||
/// assert_eq!(try_join!(a, b), Ok((1, 2)));
|
||||
///
|
||||
/// // `try_join!` is variadic, so you can pass any number of futures
|
||||
/// let c = async { Ok::<i32, i32>(3) };
|
||||
/// let d = async { Ok::<i32, i32>(4) };
|
||||
/// let e = async { Ok::<i32, i32>(5) };
|
||||
/// assert_eq!(try_join!(c, d, e), Ok((3, 4, 5)));
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// If one of the futures resolves to an error, `try_join!` will return
|
||||
/// that error:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::try_join;
|
||||
///
|
||||
/// let a = async { Ok::<i32, i32>(1) };
|
||||
/// let b = async { Err::<u64, i32>(2) };
|
||||
///
|
||||
/// assert_eq!(try_join!(a, b), Err(2));
|
||||
/// # });
|
||||
/// ```
|
||||
$try_join
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
#[doc(hidden)]
|
||||
pub use futures_macro::join_internal;
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
#[doc(hidden)]
|
||||
pub use futures_macro::try_join_internal;
|
||||
|
||||
document_join_macro! {
|
||||
#[macro_export]
|
||||
macro_rules! join {
|
||||
($($tokens:tt)*) => {{
|
||||
use $crate::__private as __futures_crate;
|
||||
$crate::join_internal! {
|
||||
$( $tokens )*
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! try_join {
|
||||
($($tokens:tt)*) => {{
|
||||
use $crate::__private as __futures_crate;
|
||||
$crate::try_join_internal! {
|
||||
$( $tokens )*
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
58
zeroidc/vendor/futures-util/src/async_await/mod.rs
vendored
Normal file
58
zeroidc/vendor/futures-util/src/async_await/mod.rs
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
//! Await
|
||||
//!
|
||||
//! This module contains a number of functions and combinators for working
|
||||
//! with `async`/`await` code.
|
||||
|
||||
use futures_core::future::{FusedFuture, Future};
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
|
||||
#[macro_use]
|
||||
mod poll;
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
|
||||
pub use self::poll::*;
|
||||
|
||||
#[macro_use]
|
||||
mod pending;
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
|
||||
pub use self::pending::*;
|
||||
|
||||
// Primary export is a macro
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
mod join_mod;
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
pub use self::join_mod::*;
|
||||
|
||||
// Primary export is a macro
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
mod select_mod;
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
pub use self::select_mod::*;
|
||||
|
||||
// Primary export is a macro
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
mod stream_select_mod;
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
pub use self::stream_select_mod::*;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
mod random;
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/64762
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(feature = "async-await-macro")]
|
||||
pub use self::random::*;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
pub fn assert_unpin<T: Unpin>(_: &T) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
pub fn assert_fused_future<T: Future + FusedFuture>(_: &T) {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
pub fn assert_fused_stream<T: Stream + FusedStream>(_: &T) {}
|
||||
43
zeroidc/vendor/futures-util/src/async_await/pending.rs
vendored
Normal file
43
zeroidc/vendor/futures-util/src/async_await/pending.rs
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
|
||||
/// A macro which yields to the event loop once.
|
||||
///
|
||||
/// This is equivalent to returning [`Poll::Pending`](futures_core::task::Poll)
|
||||
/// from a [`Future::poll`](futures_core::future::Future::poll) implementation.
|
||||
/// Similarly, when using this macro, it must be ensured that [`wake`](std::task::Waker::wake)
|
||||
/// is called somewhere when further progress can be made.
|
||||
///
|
||||
/// This macro is only usable inside of async functions, closures, and blocks.
|
||||
/// It is also gated behind the `async-await` feature of this library, which is
|
||||
/// activated by default.
|
||||
#[macro_export]
|
||||
macro_rules! pending {
|
||||
() => {
|
||||
$crate::__private::async_await::pending_once().await
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn pending_once() -> PendingOnce {
|
||||
PendingOnce { is_ready: false }
|
||||
}
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[doc(hidden)]
|
||||
pub struct PendingOnce {
|
||||
is_ready: bool,
|
||||
}
|
||||
|
||||
impl Future for PendingOnce {
|
||||
type Output = ();
|
||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.is_ready {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
self.is_ready = true;
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
39
zeroidc/vendor/futures-util/src/async_await/poll.rs
vendored
Normal file
39
zeroidc/vendor/futures-util/src/async_await/poll.rs
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
use crate::future::FutureExt;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
|
||||
/// A macro which returns the result of polling a future once within the
|
||||
/// current `async` context.
|
||||
///
|
||||
/// This macro is only usable inside of `async` functions, closures, and blocks.
|
||||
/// It is also gated behind the `async-await` feature of this library, which is
|
||||
/// activated by default.
|
||||
///
|
||||
/// If you need the result of polling a [`Stream`](crate::stream::Stream),
|
||||
/// you can use this macro with the [`next`](crate::stream::StreamExt::next) method:
|
||||
/// `poll!(stream.next())`.
|
||||
#[macro_export]
|
||||
macro_rules! poll {
|
||||
($x:expr $(,)?) => {
|
||||
$crate::__private::async_await::poll($x).await
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn poll<F: Future + Unpin>(future: F) -> PollOnce<F> {
|
||||
PollOnce { future }
|
||||
}
|
||||
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[doc(hidden)]
|
||||
pub struct PollOnce<F: Future + Unpin> {
|
||||
future: F,
|
||||
}
|
||||
|
||||
impl<F: Future + Unpin> Future for PollOnce<F> {
|
||||
type Output = Poll<F::Output>;
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(self.future.poll_unpin(cx))
|
||||
}
|
||||
}
|
||||
54
zeroidc/vendor/futures-util/src/async_await/random.rs
vendored
Normal file
54
zeroidc/vendor/futures-util/src/async_await/random.rs
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
use std::{
|
||||
cell::Cell,
|
||||
collections::hash_map::DefaultHasher,
|
||||
hash::Hasher,
|
||||
num::Wrapping,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
// Based on [Fisher–Yates shuffle].
|
||||
//
|
||||
// [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
|
||||
#[doc(hidden)]
|
||||
pub fn shuffle<T>(slice: &mut [T]) {
|
||||
for i in (1..slice.len()).rev() {
|
||||
slice.swap(i, gen_index(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a value from `0..n`.
|
||||
fn gen_index(n: usize) -> usize {
|
||||
(random() % n as u64) as usize
|
||||
}
|
||||
|
||||
/// Pseudorandom number generator based on [xorshift*].
|
||||
///
|
||||
/// [xorshift*]: https://en.wikipedia.org/wiki/Xorshift#xorshift*
|
||||
fn random() -> u64 {
|
||||
thread_local! {
|
||||
static RNG: Cell<Wrapping<u64>> = Cell::new(Wrapping(prng_seed()));
|
||||
}
|
||||
|
||||
fn prng_seed() -> u64 {
|
||||
static COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
// Any non-zero seed will do
|
||||
let mut seed = 0;
|
||||
while seed == 0 {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
hasher.write_usize(COUNTER.fetch_add(1, Ordering::Relaxed));
|
||||
seed = hasher.finish();
|
||||
}
|
||||
seed
|
||||
}
|
||||
|
||||
RNG.with(|rng| {
|
||||
let mut x = rng.get();
|
||||
debug_assert_ne!(x.0, 0);
|
||||
x ^= x >> 12;
|
||||
x ^= x << 25;
|
||||
x ^= x >> 27;
|
||||
rng.set(x);
|
||||
x.0.wrapping_mul(0x2545_f491_4f6c_dd1d)
|
||||
})
|
||||
}
|
||||
336
zeroidc/vendor/futures-util/src/async_await/select_mod.rs
vendored
Normal file
336
zeroidc/vendor/futures-util/src/async_await/select_mod.rs
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
//! The `select` macro.
|
||||
|
||||
macro_rules! document_select_macro {
|
||||
// This branch is required for `futures 0.3.1`, from before select_biased was introduced
|
||||
($select:item) => {
|
||||
/// Polls multiple futures and streams simultaneously, executing the branch
|
||||
/// for the future that finishes first. If multiple futures are ready,
|
||||
/// one will be pseudo-randomly selected at runtime. Futures directly
|
||||
/// passed to `select!` must be `Unpin` and implement `FusedFuture`.
|
||||
///
|
||||
/// If an expression which yields a `Future` is passed to `select!`
|
||||
/// (e.g. an `async fn` call) instead of a `Future` by name the `Unpin`
|
||||
/// requirement is relaxed, since the macro will pin the resulting `Future`
|
||||
/// on the stack. However the `Future` returned by the expression must
|
||||
/// still implement `FusedFuture`.
|
||||
///
|
||||
/// Futures and streams which are not already fused can be fused using the
|
||||
/// `.fuse()` method. Note, though, that fusing a future or stream directly
|
||||
/// in the call to `select!` will not be enough to prevent it from being
|
||||
/// polled after completion if the `select!` call is in a loop, so when
|
||||
/// `select!`ing in a loop, users should take care to `fuse()` outside of
|
||||
/// the loop.
|
||||
///
|
||||
/// `select!` can be used as an expression and will return the return
|
||||
/// value of the selected branch. For this reason the return type of every
|
||||
/// branch in a `select!` must be the same.
|
||||
///
|
||||
/// This macro is only usable inside of async functions, closures, and blocks.
|
||||
/// It is also gated behind the `async-await` feature of this library, which is
|
||||
/// activated by default.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future;
|
||||
/// use futures::select;
|
||||
/// let mut a = future::ready(4);
|
||||
/// let mut b = future::pending::<()>();
|
||||
///
|
||||
/// let res = select! {
|
||||
/// a_res = a => a_res + 1,
|
||||
/// _ = b => 0,
|
||||
/// };
|
||||
/// assert_eq!(res, 5);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future;
|
||||
/// use futures::stream::{self, StreamExt};
|
||||
/// use futures::select;
|
||||
/// let mut st = stream::iter(vec![2]).fuse();
|
||||
/// let mut fut = future::pending::<()>();
|
||||
///
|
||||
/// select! {
|
||||
/// x = st.next() => assert_eq!(Some(2), x),
|
||||
/// _ = fut => panic!(),
|
||||
/// };
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// As described earlier, `select` can directly select on expressions
|
||||
/// which return `Future`s - even if those do not implement `Unpin`:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future::FutureExt;
|
||||
/// use futures::select;
|
||||
///
|
||||
/// // Calling the following async fn returns a Future which does not
|
||||
/// // implement Unpin
|
||||
/// async fn async_identity_fn(arg: usize) -> usize {
|
||||
/// arg
|
||||
/// }
|
||||
///
|
||||
/// let res = select! {
|
||||
/// a_res = async_identity_fn(62).fuse() => a_res + 1,
|
||||
/// b_res = async_identity_fn(13).fuse() => b_res,
|
||||
/// };
|
||||
/// assert!(res == 63 || res == 13);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// If a similar async function is called outside of `select` to produce
|
||||
/// a `Future`, the `Future` must be pinned in order to be able to pass
|
||||
/// it to `select`. This can be achieved via `Box::pin` for pinning a
|
||||
/// `Future` on the heap or the `pin_mut!` macro for pinning a `Future`
|
||||
/// on the stack.
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future::FutureExt;
|
||||
/// use futures::select;
|
||||
/// use futures::pin_mut;
|
||||
///
|
||||
/// // Calling the following async fn returns a Future which does not
|
||||
/// // implement Unpin
|
||||
/// async fn async_identity_fn(arg: usize) -> usize {
|
||||
/// arg
|
||||
/// }
|
||||
///
|
||||
/// let fut_1 = async_identity_fn(1).fuse();
|
||||
/// let fut_2 = async_identity_fn(2).fuse();
|
||||
/// let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap
|
||||
/// pin_mut!(fut_2); // Pins the Future on the stack
|
||||
///
|
||||
/// let res = select! {
|
||||
/// a_res = fut_1 => a_res,
|
||||
/// b_res = fut_2 => b_res,
|
||||
/// };
|
||||
/// assert!(res == 1 || res == 2);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// `select` also accepts a `complete` branch and a `default` branch.
|
||||
/// `complete` will run if all futures and streams have already been
|
||||
/// exhausted. `default` will run if no futures or streams are
|
||||
/// immediately ready. `complete` takes priority over `default` in
|
||||
/// the case where all futures have completed.
|
||||
/// A motivating use-case for passing `Future`s by name as well as for
|
||||
/// `complete` blocks is to call `select!` in a loop, which is
|
||||
/// demonstrated in the following example:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future;
|
||||
/// use futures::select;
|
||||
/// let mut a_fut = future::ready(4);
|
||||
/// let mut b_fut = future::ready(6);
|
||||
/// let mut total = 0;
|
||||
///
|
||||
/// loop {
|
||||
/// select! {
|
||||
/// a = a_fut => total += a,
|
||||
/// b = b_fut => total += b,
|
||||
/// complete => break,
|
||||
/// default => panic!(), // never runs (futures run first, then complete)
|
||||
/// };
|
||||
/// }
|
||||
/// assert_eq!(total, 10);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// Note that the futures that have been matched over can still be mutated
|
||||
/// from inside the `select!` block's branches. This can be used to implement
|
||||
/// more complex behavior such as timer resets or writing into the head of
|
||||
/// a stream.
|
||||
$select
|
||||
};
|
||||
|
||||
($select:item $select_biased:item) => {
|
||||
document_select_macro!($select);
|
||||
|
||||
/// Polls multiple futures and streams simultaneously, executing the branch
|
||||
/// for the future that finishes first. Unlike [`select!`], if multiple futures are ready,
|
||||
/// one will be selected in order of declaration. Futures directly
|
||||
/// passed to `select_biased!` must be `Unpin` and implement `FusedFuture`.
|
||||
///
|
||||
/// If an expression which yields a `Future` is passed to `select_biased!`
|
||||
/// (e.g. an `async fn` call) instead of a `Future` by name the `Unpin`
|
||||
/// requirement is relaxed, since the macro will pin the resulting `Future`
|
||||
/// on the stack. However the `Future` returned by the expression must
|
||||
/// still implement `FusedFuture`.
|
||||
///
|
||||
/// Futures and streams which are not already fused can be fused using the
|
||||
/// `.fuse()` method. Note, though, that fusing a future or stream directly
|
||||
/// in the call to `select_biased!` will not be enough to prevent it from being
|
||||
/// polled after completion if the `select_biased!` call is in a loop, so when
|
||||
/// `select_biased!`ing in a loop, users should take care to `fuse()` outside of
|
||||
/// the loop.
|
||||
///
|
||||
/// `select_biased!` can be used as an expression and will return the return
|
||||
/// value of the selected branch. For this reason the return type of every
|
||||
/// branch in a `select_biased!` must be the same.
|
||||
///
|
||||
/// This macro is only usable inside of async functions, closures, and blocks.
|
||||
/// It is also gated behind the `async-await` feature of this library, which is
|
||||
/// activated by default.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future;
|
||||
/// use futures::select_biased;
|
||||
/// let mut a = future::ready(4);
|
||||
/// let mut b = future::pending::<()>();
|
||||
///
|
||||
/// let res = select_biased! {
|
||||
/// a_res = a => a_res + 1,
|
||||
/// _ = b => 0,
|
||||
/// };
|
||||
/// assert_eq!(res, 5);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future;
|
||||
/// use futures::stream::{self, StreamExt};
|
||||
/// use futures::select_biased;
|
||||
/// let mut st = stream::iter(vec![2]).fuse();
|
||||
/// let mut fut = future::pending::<()>();
|
||||
///
|
||||
/// select_biased! {
|
||||
/// x = st.next() => assert_eq!(Some(2), x),
|
||||
/// _ = fut => panic!(),
|
||||
/// };
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// As described earlier, `select_biased` can directly select on expressions
|
||||
/// which return `Future`s - even if those do not implement `Unpin`:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future::FutureExt;
|
||||
/// use futures::select_biased;
|
||||
///
|
||||
/// // Calling the following async fn returns a Future which does not
|
||||
/// // implement Unpin
|
||||
/// async fn async_identity_fn(arg: usize) -> usize {
|
||||
/// arg
|
||||
/// }
|
||||
///
|
||||
/// let res = select_biased! {
|
||||
/// a_res = async_identity_fn(62).fuse() => a_res + 1,
|
||||
/// b_res = async_identity_fn(13).fuse() => b_res,
|
||||
/// };
|
||||
/// assert!(res == 63 || res == 12);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// If a similar async function is called outside of `select_biased` to produce
|
||||
/// a `Future`, the `Future` must be pinned in order to be able to pass
|
||||
/// it to `select_biased`. This can be achieved via `Box::pin` for pinning a
|
||||
/// `Future` on the heap or the `pin_mut!` macro for pinning a `Future`
|
||||
/// on the stack.
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future::FutureExt;
|
||||
/// use futures::select_biased;
|
||||
/// use futures::pin_mut;
|
||||
///
|
||||
/// // Calling the following async fn returns a Future which does not
|
||||
/// // implement Unpin
|
||||
/// async fn async_identity_fn(arg: usize) -> usize {
|
||||
/// arg
|
||||
/// }
|
||||
///
|
||||
/// let fut_1 = async_identity_fn(1).fuse();
|
||||
/// let fut_2 = async_identity_fn(2).fuse();
|
||||
/// let mut fut_1 = Box::pin(fut_1); // Pins the Future on the heap
|
||||
/// pin_mut!(fut_2); // Pins the Future on the stack
|
||||
///
|
||||
/// let res = select_biased! {
|
||||
/// a_res = fut_1 => a_res,
|
||||
/// b_res = fut_2 => b_res,
|
||||
/// };
|
||||
/// assert!(res == 1 || res == 2);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// `select_biased` also accepts a `complete` branch and a `default` branch.
|
||||
/// `complete` will run if all futures and streams have already been
|
||||
/// exhausted. `default` will run if no futures or streams are
|
||||
/// immediately ready. `complete` takes priority over `default` in
|
||||
/// the case where all futures have completed.
|
||||
/// A motivating use-case for passing `Future`s by name as well as for
|
||||
/// `complete` blocks is to call `select_biased!` in a loop, which is
|
||||
/// demonstrated in the following example:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::future;
|
||||
/// use futures::select_biased;
|
||||
/// let mut a_fut = future::ready(4);
|
||||
/// let mut b_fut = future::ready(6);
|
||||
/// let mut total = 0;
|
||||
///
|
||||
/// loop {
|
||||
/// select_biased! {
|
||||
/// a = a_fut => total += a,
|
||||
/// b = b_fut => total += b,
|
||||
/// complete => break,
|
||||
/// default => panic!(), // never runs (futures run first, then complete)
|
||||
/// };
|
||||
/// }
|
||||
/// assert_eq!(total, 10);
|
||||
/// # });
|
||||
/// ```
|
||||
///
|
||||
/// Note that the futures that have been matched over can still be mutated
|
||||
/// from inside the `select_biased!` block's branches. This can be used to implement
|
||||
/// more complex behavior such as timer resets or writing into the head of
|
||||
/// a stream.
|
||||
///
|
||||
/// [`select!`]: macro.select.html
|
||||
$select_biased
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[allow(unreachable_pub)]
|
||||
#[doc(hidden)]
|
||||
pub use futures_macro::select_internal;
|
||||
|
||||
#[allow(unreachable_pub)]
|
||||
#[doc(hidden)]
|
||||
pub use futures_macro::select_biased_internal;
|
||||
|
||||
document_select_macro! {
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_export]
|
||||
macro_rules! select {
|
||||
($($tokens:tt)*) => {{
|
||||
use $crate::__private as __futures_crate;
|
||||
$crate::select_internal! {
|
||||
$( $tokens )*
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! select_biased {
|
||||
($($tokens:tt)*) => {{
|
||||
use $crate::__private as __futures_crate;
|
||||
$crate::select_biased_internal! {
|
||||
$( $tokens )*
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
40
zeroidc/vendor/futures-util/src/async_await/stream_select_mod.rs
vendored
Normal file
40
zeroidc/vendor/futures-util/src/async_await/stream_select_mod.rs
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
//! The `stream_select` macro.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[allow(unreachable_pub)]
|
||||
#[doc(hidden)]
|
||||
pub use futures_macro::stream_select_internal;
|
||||
|
||||
/// Combines several streams, all producing the same `Item` type, into one stream.
|
||||
/// This is similar to `select_all` but does not require the streams to all be the same type.
|
||||
/// It also keeps the streams inline, and does not require `Box<dyn Stream>`s to be allocated.
|
||||
/// Streams passed to this macro must be `Unpin`.
|
||||
///
|
||||
/// If multiple streams are ready, one will be pseudo randomly selected at runtime.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::{stream, StreamExt, stream_select};
|
||||
/// let endless_ints = |i| stream::iter(vec![i].into_iter().cycle()).fuse();
|
||||
///
|
||||
/// let mut endless_numbers = stream_select!(endless_ints(1i32), endless_ints(2), endless_ints(3));
|
||||
/// match endless_numbers.next().await {
|
||||
/// Some(1) => println!("Got a 1"),
|
||||
/// Some(2) => println!("Got a 2"),
|
||||
/// Some(3) => println!("Got a 3"),
|
||||
/// _ => unreachable!(),
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_export]
|
||||
macro_rules! stream_select {
|
||||
($($tokens:tt)*) => {{
|
||||
use $crate::__private as __futures_crate;
|
||||
$crate::stream_select_internal! {
|
||||
$( $tokens )*
|
||||
}
|
||||
}}
|
||||
}
|
||||
454
zeroidc/vendor/futures-util/src/compat/compat01as03.rs
vendored
Normal file
454
zeroidc/vendor/futures-util/src/compat/compat01as03.rs
vendored
Normal file
@@ -0,0 +1,454 @@
|
||||
use futures_01::executor::{
|
||||
spawn as spawn01, Notify as Notify01, NotifyHandle as NotifyHandle01, Spawn as Spawn01,
|
||||
UnsafeNotify as UnsafeNotify01,
|
||||
};
|
||||
use futures_01::{Async as Async01, Future as Future01, Stream as Stream01};
|
||||
#[cfg(feature = "sink")]
|
||||
use futures_01::{AsyncSink as AsyncSink01, Sink as Sink01};
|
||||
use futures_core::{future::Future as Future03, stream::Stream as Stream03, task as task03};
|
||||
#[cfg(feature = "sink")]
|
||||
use futures_sink::Sink as Sink03;
|
||||
use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
|
||||
pub use io::{AsyncRead01CompatExt, AsyncWrite01CompatExt};
|
||||
|
||||
/// Converts a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite
|
||||
/// object to a futures 0.3-compatible version,
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Compat01As03<T> {
|
||||
pub(crate) inner: Spawn01<T>,
|
||||
}
|
||||
|
||||
impl<T> Unpin for Compat01As03<T> {}
|
||||
|
||||
impl<T> Compat01As03<T> {
|
||||
/// Wraps a futures 0.1 Future, Stream, AsyncRead, or AsyncWrite
|
||||
/// object in a futures 0.3-compatible wrapper.
|
||||
pub fn new(object: T) -> Self {
|
||||
Self { inner: spawn01(object) }
|
||||
}
|
||||
|
||||
fn in_notify<R>(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut T) -> R) -> R {
|
||||
let notify = &WakerToHandle(cx.waker());
|
||||
self.inner.poll_fn_notify(notify, 0, f)
|
||||
}
|
||||
|
||||
/// Get a reference to 0.1 Future, Stream, AsyncRead, or AsyncWrite object contained within.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
self.inner.get_ref()
|
||||
}
|
||||
|
||||
/// Get a mutable reference to 0.1 Future, Stream, AsyncRead or AsyncWrite object contained
|
||||
/// within.
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
self.inner.get_mut()
|
||||
}
|
||||
|
||||
/// Consume this wrapper to return the underlying 0.1 Future, Stream, AsyncRead, or
|
||||
/// AsyncWrite object.
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for futures 0.1 [`Future`](futures_01::future::Future)
|
||||
pub trait Future01CompatExt: Future01 {
|
||||
/// Converts a futures 0.1
|
||||
/// [`Future<Item = T, Error = E>`](futures_01::future::Future)
|
||||
/// into a futures 0.3
|
||||
/// [`Future<Output = Result<T, E>>`](futures_core::future::Future).
|
||||
///
|
||||
/// ```
|
||||
/// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514
|
||||
/// # futures::executor::block_on(async {
|
||||
/// # // TODO: These should be all using `futures::compat`, but that runs up against Cargo
|
||||
/// # // feature issues
|
||||
/// use futures_util::compat::Future01CompatExt;
|
||||
///
|
||||
/// let future = futures_01::future::ok::<u32, ()>(1);
|
||||
/// assert_eq!(future.compat().await, Ok(1));
|
||||
/// # });
|
||||
/// ```
|
||||
fn compat(self) -> Compat01As03<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compat01As03::new(self)
|
||||
}
|
||||
}
|
||||
impl<Fut: Future01> Future01CompatExt for Fut {}
|
||||
|
||||
/// Extension trait for futures 0.1 [`Stream`](futures_01::stream::Stream)
|
||||
pub trait Stream01CompatExt: Stream01 {
|
||||
/// Converts a futures 0.1
|
||||
/// [`Stream<Item = T, Error = E>`](futures_01::stream::Stream)
|
||||
/// into a futures 0.3
|
||||
/// [`Stream<Item = Result<T, E>>`](futures_core::stream::Stream).
|
||||
///
|
||||
/// ```
|
||||
/// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::stream::StreamExt;
|
||||
/// use futures_util::compat::Stream01CompatExt;
|
||||
///
|
||||
/// let stream = futures_01::stream::once::<u32, ()>(Ok(1));
|
||||
/// let mut stream = stream.compat();
|
||||
/// assert_eq!(stream.next().await, Some(Ok(1)));
|
||||
/// assert_eq!(stream.next().await, None);
|
||||
/// # });
|
||||
/// ```
|
||||
fn compat(self) -> Compat01As03<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compat01As03::new(self)
|
||||
}
|
||||
}
|
||||
impl<St: Stream01> Stream01CompatExt for St {}
|
||||
|
||||
/// Extension trait for futures 0.1 [`Sink`](futures_01::sink::Sink)
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
pub trait Sink01CompatExt: Sink01 {
|
||||
/// Converts a futures 0.1
|
||||
/// [`Sink<SinkItem = T, SinkError = E>`](futures_01::sink::Sink)
|
||||
/// into a futures 0.3
|
||||
/// [`Sink<T, Error = E>`](futures_sink::Sink).
|
||||
///
|
||||
/// ```
|
||||
/// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::{sink::SinkExt, stream::StreamExt};
|
||||
/// use futures_util::compat::{Stream01CompatExt, Sink01CompatExt};
|
||||
///
|
||||
/// let (tx, rx) = futures_01::unsync::mpsc::channel(1);
|
||||
/// let (mut tx, mut rx) = (tx.sink_compat(), rx.compat());
|
||||
///
|
||||
/// tx.send(1).await.unwrap();
|
||||
/// drop(tx);
|
||||
/// assert_eq!(rx.next().await, Some(Ok(1)));
|
||||
/// assert_eq!(rx.next().await, None);
|
||||
/// # });
|
||||
/// ```
|
||||
fn sink_compat(self) -> Compat01As03Sink<Self, Self::SinkItem>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compat01As03Sink::new(self)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sink")]
|
||||
impl<Si: Sink01> Sink01CompatExt for Si {}
|
||||
|
||||
fn poll_01_to_03<T, E>(x: Result<Async01<T>, E>) -> task03::Poll<Result<T, E>> {
|
||||
match x? {
|
||||
Async01::Ready(t) => task03::Poll::Ready(Ok(t)),
|
||||
Async01::NotReady => task03::Poll::Pending,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future01> Future03 for Compat01As03<Fut> {
|
||||
type Output = Result<Fut::Item, Fut::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> task03::Poll<Self::Output> {
|
||||
poll_01_to_03(self.in_notify(cx, Future01::poll))
|
||||
}
|
||||
}
|
||||
|
||||
impl<St: Stream01> Stream03 for Compat01As03<St> {
|
||||
type Item = Result<St::Item, St::Error>;
|
||||
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Option<Self::Item>> {
|
||||
match self.in_notify(cx, Stream01::poll)? {
|
||||
Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))),
|
||||
Async01::Ready(None) => task03::Poll::Ready(None),
|
||||
Async01::NotReady => task03::Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a futures 0.1 Sink object to a futures 0.3-compatible version
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
#[derive(Debug)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct Compat01As03Sink<S, SinkItem> {
|
||||
pub(crate) inner: Spawn01<S>,
|
||||
pub(crate) buffer: Option<SinkItem>,
|
||||
pub(crate) close_started: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<S, SinkItem> Unpin for Compat01As03Sink<S, SinkItem> {}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<S, SinkItem> Compat01As03Sink<S, SinkItem> {
|
||||
/// Wraps a futures 0.1 Sink object in a futures 0.3-compatible wrapper.
|
||||
pub fn new(inner: S) -> Self {
|
||||
Self { inner: spawn01(inner), buffer: None, close_started: false }
|
||||
}
|
||||
|
||||
fn in_notify<R>(&mut self, cx: &mut Context<'_>, f: impl FnOnce(&mut S) -> R) -> R {
|
||||
let notify = &WakerToHandle(cx.waker());
|
||||
self.inner.poll_fn_notify(notify, 0, f)
|
||||
}
|
||||
|
||||
/// Get a reference to 0.1 Sink object contained within.
|
||||
pub fn get_ref(&self) -> &S {
|
||||
self.inner.get_ref()
|
||||
}
|
||||
|
||||
/// Get a mutable reference to 0.1 Sink contained within.
|
||||
pub fn get_mut(&mut self) -> &mut S {
|
||||
self.inner.get_mut()
|
||||
}
|
||||
|
||||
/// Consume this wrapper to return the underlying 0.1 Sink.
|
||||
pub fn into_inner(self) -> S {
|
||||
self.inner.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<S, SinkItem> Stream03 for Compat01As03Sink<S, SinkItem>
|
||||
where
|
||||
S: Stream01,
|
||||
{
|
||||
type Item = Result<S::Item, S::Error>;
|
||||
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Option<Self::Item>> {
|
||||
match self.in_notify(cx, Stream01::poll)? {
|
||||
Async01::Ready(Some(t)) => task03::Poll::Ready(Some(Ok(t))),
|
||||
Async01::Ready(None) => task03::Poll::Ready(None),
|
||||
Async01::NotReady => task03::Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<S, SinkItem> Sink03<SinkItem> for Compat01As03Sink<S, SinkItem>
|
||||
where
|
||||
S: Sink01<SinkItem = SinkItem>,
|
||||
{
|
||||
type Error = S::SinkError;
|
||||
|
||||
fn start_send(mut self: Pin<&mut Self>, item: SinkItem) -> Result<(), Self::Error> {
|
||||
debug_assert!(self.buffer.is_none());
|
||||
self.buffer = Some(item);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_ready(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Result<(), Self::Error>> {
|
||||
match self.buffer.take() {
|
||||
Some(item) => match self.in_notify(cx, |f| f.start_send(item))? {
|
||||
AsyncSink01::Ready => task03::Poll::Ready(Ok(())),
|
||||
AsyncSink01::NotReady(i) => {
|
||||
self.buffer = Some(i);
|
||||
task03::Poll::Pending
|
||||
}
|
||||
},
|
||||
None => task03::Poll::Ready(Ok(())),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_flush(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Result<(), Self::Error>> {
|
||||
let item = self.buffer.take();
|
||||
match self.in_notify(cx, |f| match item {
|
||||
Some(i) => match f.start_send(i)? {
|
||||
AsyncSink01::Ready => f.poll_complete().map(|i| (i, None)),
|
||||
AsyncSink01::NotReady(t) => Ok((Async01::NotReady, Some(t))),
|
||||
},
|
||||
None => f.poll_complete().map(|i| (i, None)),
|
||||
})? {
|
||||
(Async01::Ready(_), _) => task03::Poll::Ready(Ok(())),
|
||||
(Async01::NotReady, item) => {
|
||||
self.buffer = item;
|
||||
task03::Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_close(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Result<(), Self::Error>> {
|
||||
let item = self.buffer.take();
|
||||
let close_started = self.close_started;
|
||||
|
||||
let result = self.in_notify(cx, |f| {
|
||||
if !close_started {
|
||||
if let Some(item) = item {
|
||||
if let AsyncSink01::NotReady(item) = f.start_send(item)? {
|
||||
return Ok((Async01::NotReady, Some(item), false));
|
||||
}
|
||||
}
|
||||
|
||||
if let Async01::NotReady = f.poll_complete()? {
|
||||
return Ok((Async01::NotReady, None, false));
|
||||
}
|
||||
}
|
||||
|
||||
Ok((<S as Sink01>::close(f)?, None, true))
|
||||
});
|
||||
|
||||
match result? {
|
||||
(Async01::Ready(_), _, _) => task03::Poll::Ready(Ok(())),
|
||||
(Async01::NotReady, item, close_started) => {
|
||||
self.buffer = item;
|
||||
self.close_started = close_started;
|
||||
task03::Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NotifyWaker(task03::Waker);
|
||||
|
||||
#[allow(missing_debug_implementations)] // false positive: this is private type
|
||||
#[derive(Clone)]
|
||||
struct WakerToHandle<'a>(&'a task03::Waker);
|
||||
|
||||
impl From<WakerToHandle<'_>> for NotifyHandle01 {
|
||||
fn from(handle: WakerToHandle<'_>) -> Self {
|
||||
let ptr = Box::new(NotifyWaker(handle.0.clone()));
|
||||
|
||||
unsafe { Self::new(Box::into_raw(ptr)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Notify01 for NotifyWaker {
|
||||
fn notify(&self, _: usize) {
|
||||
self.0.wake_by_ref();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl UnsafeNotify01 for NotifyWaker {
|
||||
unsafe fn clone_raw(&self) -> NotifyHandle01 {
|
||||
WakerToHandle(&self.0).into()
|
||||
}
|
||||
|
||||
unsafe fn drop_raw(&self) {
|
||||
let ptr: *const dyn UnsafeNotify01 = self;
|
||||
drop(Box::from_raw(ptr as *mut dyn UnsafeNotify01));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
mod io {
|
||||
use super::*;
|
||||
use futures_io::{AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03};
|
||||
use std::io::Error;
|
||||
use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01};
|
||||
|
||||
/// Extension trait for tokio-io [`AsyncRead`](tokio_io::AsyncRead)
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
pub trait AsyncRead01CompatExt: AsyncRead01 {
|
||||
/// Converts a tokio-io [`AsyncRead`](tokio_io::AsyncRead) into a futures-io 0.3
|
||||
/// [`AsyncRead`](futures_io::AsyncRead).
|
||||
///
|
||||
/// ```
|
||||
/// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::AsyncReadExt;
|
||||
/// use futures_util::compat::AsyncRead01CompatExt;
|
||||
///
|
||||
/// let input = b"Hello World!";
|
||||
/// let reader /* : impl tokio_io::AsyncRead */ = std::io::Cursor::new(input);
|
||||
/// let mut reader /* : impl futures::io::AsyncRead + Unpin */ = reader.compat();
|
||||
///
|
||||
/// let mut output = Vec::with_capacity(12);
|
||||
/// reader.read_to_end(&mut output).await.unwrap();
|
||||
/// assert_eq!(output, input);
|
||||
/// # });
|
||||
/// ```
|
||||
fn compat(self) -> Compat01As03<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compat01As03::new(self)
|
||||
}
|
||||
}
|
||||
impl<R: AsyncRead01> AsyncRead01CompatExt for R {}
|
||||
|
||||
/// Extension trait for tokio-io [`AsyncWrite`](tokio_io::AsyncWrite)
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
pub trait AsyncWrite01CompatExt: AsyncWrite01 {
|
||||
/// Converts a tokio-io [`AsyncWrite`](tokio_io::AsyncWrite) into a futures-io 0.3
|
||||
/// [`AsyncWrite`](futures_io::AsyncWrite).
|
||||
///
|
||||
/// ```
|
||||
/// # if cfg!(miri) { return; } // https://github.com/rust-lang/futures-rs/issues/2514
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::AsyncWriteExt;
|
||||
/// use futures_util::compat::AsyncWrite01CompatExt;
|
||||
///
|
||||
/// let input = b"Hello World!";
|
||||
/// let mut cursor = std::io::Cursor::new(Vec::with_capacity(12));
|
||||
///
|
||||
/// let mut writer = (&mut cursor).compat();
|
||||
/// writer.write_all(input).await.unwrap();
|
||||
///
|
||||
/// assert_eq!(cursor.into_inner(), input);
|
||||
/// # });
|
||||
/// ```
|
||||
fn compat(self) -> Compat01As03<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compat01As03::new(self)
|
||||
}
|
||||
}
|
||||
impl<W: AsyncWrite01> AsyncWrite01CompatExt for W {}
|
||||
|
||||
impl<R: AsyncRead01> AsyncRead03 for Compat01As03<R> {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> task03::Poll<Result<usize, Error>> {
|
||||
poll_01_to_03(self.in_notify(cx, |x| x.poll_read(buf)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite01> AsyncWrite03 for Compat01As03<W> {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> task03::Poll<Result<usize, Error>> {
|
||||
poll_01_to_03(self.in_notify(cx, |x| x.poll_write(buf)))
|
||||
}
|
||||
|
||||
fn poll_flush(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Result<(), Error>> {
|
||||
poll_01_to_03(self.in_notify(cx, AsyncWrite01::poll_flush))
|
||||
}
|
||||
|
||||
fn poll_close(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> task03::Poll<Result<(), Error>> {
|
||||
poll_01_to_03(self.in_notify(cx, AsyncWrite01::shutdown))
|
||||
}
|
||||
}
|
||||
}
|
||||
265
zeroidc/vendor/futures-util/src/compat/compat03as01.rs
vendored
Normal file
265
zeroidc/vendor/futures-util/src/compat/compat03as01.rs
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
use crate::task::{self as task03, ArcWake as ArcWake03, WakerRef};
|
||||
use futures_01::{
|
||||
task as task01, Async as Async01, Future as Future01, Poll as Poll01, Stream as Stream01,
|
||||
};
|
||||
#[cfg(feature = "sink")]
|
||||
use futures_01::{AsyncSink as AsyncSink01, Sink as Sink01, StartSend as StartSend01};
|
||||
use futures_core::{
|
||||
future::TryFuture as TryFuture03,
|
||||
stream::TryStream as TryStream03,
|
||||
task::{RawWaker, RawWakerVTable},
|
||||
};
|
||||
#[cfg(feature = "sink")]
|
||||
use futures_sink::Sink as Sink03;
|
||||
#[cfg(feature = "sink")]
|
||||
use std::marker::PhantomData;
|
||||
use std::{mem, pin::Pin, sync::Arc, task::Context};
|
||||
|
||||
/// Converts a futures 0.3 [`TryFuture`](futures_core::future::TryFuture) or
|
||||
/// [`TryStream`](futures_core::stream::TryStream) into a futures 0.1
|
||||
/// [`Future`](futures_01::future::Future) or
|
||||
/// [`Stream`](futures_01::stream::Stream).
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Compat<T> {
|
||||
pub(crate) inner: T,
|
||||
}
|
||||
|
||||
/// Converts a futures 0.3 [`Sink`](futures_sink::Sink) into a futures 0.1
|
||||
/// [`Sink`](futures_01::sink::Sink).
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
#[derive(Debug)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct CompatSink<T, Item> {
|
||||
inner: T,
|
||||
_phantom: PhantomData<fn(Item)>,
|
||||
}
|
||||
|
||||
impl<T> Compat<T> {
|
||||
/// Creates a new [`Compat`].
|
||||
///
|
||||
/// For types which implement appropriate futures `0.3`
|
||||
/// traits, the result will be a type which implements
|
||||
/// the corresponding futures 0.1 type.
|
||||
pub fn new(inner: T) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
/// Get a reference to 0.3 Future, Stream, AsyncRead, or AsyncWrite object
|
||||
/// contained within.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Get a mutable reference to 0.3 Future, Stream, AsyncRead, or AsyncWrite object
|
||||
/// contained within.
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
/// Returns the inner item.
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<T, Item> CompatSink<T, Item> {
|
||||
/// Creates a new [`CompatSink`].
|
||||
pub fn new(inner: T) -> Self {
|
||||
Self { inner, _phantom: PhantomData }
|
||||
}
|
||||
|
||||
/// Get a reference to 0.3 Sink contained within.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Get a mutable reference to 0.3 Sink contained within.
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
/// Returns the inner item.
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_03_to_01<T, E>(x: task03::Poll<Result<T, E>>) -> Result<Async01<T>, E> {
|
||||
match x? {
|
||||
task03::Poll::Ready(t) => Ok(Async01::Ready(t)),
|
||||
task03::Poll::Pending => Ok(Async01::NotReady),
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Future01 for Compat<Fut>
|
||||
where
|
||||
Fut: TryFuture03 + Unpin,
|
||||
{
|
||||
type Item = Fut::Ok;
|
||||
type Error = Fut::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll01<Self::Item, Self::Error> {
|
||||
with_context(self, |inner, cx| poll_03_to_01(inner.try_poll(cx)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<St> Stream01 for Compat<St>
|
||||
where
|
||||
St: TryStream03 + Unpin,
|
||||
{
|
||||
type Item = St::Ok;
|
||||
type Error = St::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll01<Option<Self::Item>, Self::Error> {
|
||||
with_context(self, |inner, cx| match inner.try_poll_next(cx)? {
|
||||
task03::Poll::Ready(None) => Ok(Async01::Ready(None)),
|
||||
task03::Poll::Ready(Some(t)) => Ok(Async01::Ready(Some(t))),
|
||||
task03::Poll::Pending => Ok(Async01::NotReady),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
impl<T, Item> Sink01 for CompatSink<T, Item>
|
||||
where
|
||||
T: Sink03<Item> + Unpin,
|
||||
{
|
||||
type SinkItem = Item;
|
||||
type SinkError = T::Error;
|
||||
|
||||
fn start_send(&mut self, item: Self::SinkItem) -> StartSend01<Self::SinkItem, Self::SinkError> {
|
||||
with_sink_context(self, |mut inner, cx| match inner.as_mut().poll_ready(cx)? {
|
||||
task03::Poll::Ready(()) => inner.start_send(item).map(|()| AsyncSink01::Ready),
|
||||
task03::Poll::Pending => Ok(AsyncSink01::NotReady(item)),
|
||||
})
|
||||
}
|
||||
|
||||
fn poll_complete(&mut self) -> Poll01<(), Self::SinkError> {
|
||||
with_sink_context(self, |inner, cx| poll_03_to_01(inner.poll_flush(cx)))
|
||||
}
|
||||
|
||||
fn close(&mut self) -> Poll01<(), Self::SinkError> {
|
||||
with_sink_context(self, |inner, cx| poll_03_to_01(inner.poll_close(cx)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Current(task01::Task);
|
||||
|
||||
impl Current {
|
||||
fn new() -> Self {
|
||||
Self(task01::current())
|
||||
}
|
||||
|
||||
fn as_waker(&self) -> WakerRef<'_> {
|
||||
unsafe fn ptr_to_current<'a>(ptr: *const ()) -> &'a Current {
|
||||
&*(ptr as *const Current)
|
||||
}
|
||||
fn current_to_ptr(current: &Current) -> *const () {
|
||||
current as *const Current as *const ()
|
||||
}
|
||||
|
||||
unsafe fn clone(ptr: *const ()) -> RawWaker {
|
||||
// Lazily create the `Arc` only when the waker is actually cloned.
|
||||
// FIXME: remove `transmute` when a `Waker` -> `RawWaker` conversion
|
||||
// function is landed in `core`.
|
||||
mem::transmute::<task03::Waker, RawWaker>(task03::waker(Arc::new(
|
||||
ptr_to_current(ptr).clone(),
|
||||
)))
|
||||
}
|
||||
unsafe fn drop(_: *const ()) {}
|
||||
unsafe fn wake(ptr: *const ()) {
|
||||
ptr_to_current(ptr).0.notify()
|
||||
}
|
||||
|
||||
let ptr = current_to_ptr(self);
|
||||
let vtable = &RawWakerVTable::new(clone, wake, wake, drop);
|
||||
WakerRef::new_unowned(std::mem::ManuallyDrop::new(unsafe {
|
||||
task03::Waker::from_raw(RawWaker::new(ptr, vtable))
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl ArcWake03 for Current {
|
||||
fn wake_by_ref(arc_self: &Arc<Self>) {
|
||||
arc_self.0.notify();
|
||||
}
|
||||
}
|
||||
|
||||
fn with_context<T, R, F>(compat: &mut Compat<T>, f: F) -> R
|
||||
where
|
||||
T: Unpin,
|
||||
F: FnOnce(Pin<&mut T>, &mut Context<'_>) -> R,
|
||||
{
|
||||
let current = Current::new();
|
||||
let waker = current.as_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
f(Pin::new(&mut compat.inner), &mut cx)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
fn with_sink_context<T, Item, R, F>(compat: &mut CompatSink<T, Item>, f: F) -> R
|
||||
where
|
||||
T: Unpin,
|
||||
F: FnOnce(Pin<&mut T>, &mut Context<'_>) -> R,
|
||||
{
|
||||
let current = Current::new();
|
||||
let waker = current.as_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
f(Pin::new(&mut compat.inner), &mut cx)
|
||||
}
|
||||
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
mod io {
|
||||
use super::*;
|
||||
use futures_io::{AsyncRead as AsyncRead03, AsyncWrite as AsyncWrite03};
|
||||
use tokio_io::{AsyncRead as AsyncRead01, AsyncWrite as AsyncWrite01};
|
||||
|
||||
fn poll_03_to_io<T>(x: task03::Poll<Result<T, std::io::Error>>) -> Result<T, std::io::Error> {
|
||||
match x {
|
||||
task03::Poll::Ready(Ok(t)) => Ok(t),
|
||||
task03::Poll::Pending => Err(std::io::ErrorKind::WouldBlock.into()),
|
||||
task03::Poll::Ready(Err(e)) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead03 + Unpin> std::io::Read for Compat<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let current = Current::new();
|
||||
let waker = current.as_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
poll_03_to_io(Pin::new(&mut self.inner).poll_read(&mut cx, buf))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead03 + Unpin> AsyncRead01 for Compat<R> {}
|
||||
|
||||
impl<W: AsyncWrite03 + Unpin> std::io::Write for Compat<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let current = Current::new();
|
||||
let waker = current.as_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
poll_03_to_io(Pin::new(&mut self.inner).poll_write(&mut cx, buf))
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
let current = Current::new();
|
||||
let waker = current.as_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
poll_03_to_io(Pin::new(&mut self.inner).poll_flush(&mut cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite03 + Unpin> AsyncWrite01 for Compat<W> {
|
||||
fn shutdown(&mut self) -> std::io::Result<Async01<()>> {
|
||||
let current = Current::new();
|
||||
let waker = current.as_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
poll_03_to_01(Pin::new(&mut self.inner).poll_close(&mut cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
86
zeroidc/vendor/futures-util/src/compat/executor.rs
vendored
Normal file
86
zeroidc/vendor/futures-util/src/compat/executor.rs
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
use super::{Compat, Future01CompatExt};
|
||||
use crate::{
|
||||
future::{FutureExt, TryFutureExt, UnitError},
|
||||
task::SpawnExt,
|
||||
};
|
||||
use futures_01::future::{ExecuteError as ExecuteError01, Executor as Executor01};
|
||||
use futures_01::Future as Future01;
|
||||
use futures_task::{FutureObj, Spawn as Spawn03, SpawnError as SpawnError03};
|
||||
|
||||
/// A future that can run on a futures 0.1
|
||||
/// [`Executor`](futures_01::future::Executor).
|
||||
pub type Executor01Future = Compat<UnitError<FutureObj<'static, ()>>>;
|
||||
|
||||
/// Extension trait for futures 0.1 [`Executor`](futures_01::future::Executor).
|
||||
pub trait Executor01CompatExt: Executor01<Executor01Future> + Clone + Send + 'static {
|
||||
/// Converts a futures 0.1 [`Executor`](futures_01::future::Executor) into a
|
||||
/// futures 0.3 [`Spawn`](futures_task::Spawn).
|
||||
///
|
||||
/// ```
|
||||
/// # if cfg!(miri) { return; } // Miri does not support epoll
|
||||
/// use futures::task::SpawnExt;
|
||||
/// use futures::future::{FutureExt, TryFutureExt};
|
||||
/// use futures_util::compat::Executor01CompatExt;
|
||||
/// use tokio::executor::DefaultExecutor;
|
||||
///
|
||||
/// # let (tx, rx) = futures::channel::oneshot::channel();
|
||||
///
|
||||
/// let spawner = DefaultExecutor::current().compat();
|
||||
/// let future03 = async move {
|
||||
/// println!("Running on the pool");
|
||||
/// spawner.spawn(async {
|
||||
/// println!("Spawned!");
|
||||
/// # tx.send(42).unwrap();
|
||||
/// }).unwrap();
|
||||
/// };
|
||||
///
|
||||
/// let future01 = future03.unit_error().boxed().compat();
|
||||
///
|
||||
/// tokio::run(future01);
|
||||
/// # futures::executor::block_on(rx).unwrap();
|
||||
/// ```
|
||||
fn compat(self) -> Executor01As03<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<Ex> Executor01CompatExt for Ex
|
||||
where
|
||||
Ex: Executor01<Executor01Future> + Clone + Send + 'static,
|
||||
{
|
||||
fn compat(self) -> Executor01As03<Self> {
|
||||
Executor01As03 { executor01: self }
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a futures 0.1 [`Executor`](futures_01::future::Executor) into a
|
||||
/// futures 0.3 [`Spawn`](futures_task::Spawn).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Executor01As03<Ex> {
|
||||
executor01: Ex,
|
||||
}
|
||||
|
||||
impl<Ex> Spawn03 for Executor01As03<Ex>
|
||||
where
|
||||
Ex: Executor01<Executor01Future> + Clone + Send + 'static,
|
||||
{
|
||||
fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError03> {
|
||||
let future = future.unit_error().compat();
|
||||
|
||||
self.executor01.execute(future).map_err(|_| SpawnError03::shutdown())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
||||
impl<Sp, Fut> Executor01<Fut> for Compat<Sp>
|
||||
where
|
||||
for<'a> &'a Sp: Spawn03,
|
||||
Fut: Future01<Item = (), Error = ()> + Send + 'static,
|
||||
{
|
||||
fn execute(&self, future: Fut) -> Result<(), ExecuteError01<Fut>> {
|
||||
(&self.inner)
|
||||
.spawn(future.compat().map(|_| ()))
|
||||
.expect("unable to spawn future from Compat executor");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
22
zeroidc/vendor/futures-util/src/compat/mod.rs
vendored
Normal file
22
zeroidc/vendor/futures-util/src/compat/mod.rs
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
//! Interop between `futures` 0.1 and 0.3.
|
||||
//!
|
||||
//! This module is only available when the `compat` feature of this
|
||||
//! library is activated.
|
||||
|
||||
mod executor;
|
||||
pub use self::executor::{Executor01As03, Executor01CompatExt, Executor01Future};
|
||||
|
||||
mod compat01as03;
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
pub use self::compat01as03::{AsyncRead01CompatExt, AsyncWrite01CompatExt};
|
||||
pub use self::compat01as03::{Compat01As03, Future01CompatExt, Stream01CompatExt};
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
pub use self::compat01as03::{Compat01As03Sink, Sink01CompatExt};
|
||||
|
||||
mod compat03as01;
|
||||
pub use self::compat03as01::Compat;
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
pub use self::compat03as01::CompatSink;
|
||||
372
zeroidc/vendor/futures-util/src/fns.rs
vendored
Normal file
372
zeroidc/vendor/futures-util/src/fns.rs
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
use core::fmt::{self, Debug};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
pub trait FnOnce1<A> {
|
||||
type Output;
|
||||
fn call_once(self, arg: A) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<T, A, R> FnOnce1<A> for T
|
||||
where
|
||||
T: FnOnce(A) -> R,
|
||||
{
|
||||
type Output = R;
|
||||
fn call_once(self, arg: A) -> R {
|
||||
self(arg)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FnMut1<A>: FnOnce1<A> {
|
||||
fn call_mut(&mut self, arg: A) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<T, A, R> FnMut1<A> for T
|
||||
where
|
||||
T: FnMut(A) -> R,
|
||||
{
|
||||
fn call_mut(&mut self, arg: A) -> R {
|
||||
self(arg)
|
||||
}
|
||||
}
|
||||
|
||||
// Not used, but present for completeness
|
||||
#[allow(unreachable_pub)]
|
||||
pub trait Fn1<A>: FnMut1<A> {
|
||||
fn call(&self, arg: A) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<T, A, R> Fn1<A> for T
|
||||
where
|
||||
T: Fn(A) -> R,
|
||||
{
|
||||
fn call(&self, arg: A) -> R {
|
||||
self(arg)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! trivial_fn_impls {
|
||||
($name:ident <$($arg:ident),*> $t:ty = $debug:literal) => {
|
||||
impl<$($arg),*> Copy for $t {}
|
||||
impl<$($arg),*> Clone for $t {
|
||||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl<$($arg),*> Debug for $t {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str($debug)
|
||||
}
|
||||
}
|
||||
impl<$($arg,)* A> FnMut1<A> for $t where Self: FnOnce1<A> {
|
||||
fn call_mut(&mut self, arg: A) -> Self::Output {
|
||||
self.call_once(arg)
|
||||
}
|
||||
}
|
||||
impl<$($arg,)* A> Fn1<A> for $t where Self: FnOnce1<A> {
|
||||
fn call(&self, arg: A) -> Self::Output {
|
||||
self.call_once(arg)
|
||||
}
|
||||
}
|
||||
pub(crate) fn $name<$($arg),*>() -> $t {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OkFn<E>(PhantomData<fn(E)>);
|
||||
|
||||
impl<E> Default for OkFn<E> {
|
||||
fn default() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, E> FnOnce1<A> for OkFn<E> {
|
||||
type Output = Result<A, E>;
|
||||
fn call_once(self, arg: A) -> Self::Output {
|
||||
Ok(arg)
|
||||
}
|
||||
}
|
||||
|
||||
trivial_fn_impls!(ok_fn <T> OkFn<T> = "Ok");
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct ChainFn<F, G>(F, G);
|
||||
|
||||
impl<F, G, A> FnOnce1<A> for ChainFn<F, G>
|
||||
where
|
||||
F: FnOnce1<A>,
|
||||
G: FnOnce1<F::Output>,
|
||||
{
|
||||
type Output = G::Output;
|
||||
fn call_once(self, arg: A) -> Self::Output {
|
||||
self.1.call_once(self.0.call_once(arg))
|
||||
}
|
||||
}
|
||||
impl<F, G, A> FnMut1<A> for ChainFn<F, G>
|
||||
where
|
||||
F: FnMut1<A>,
|
||||
G: FnMut1<F::Output>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: A) -> Self::Output {
|
||||
self.1.call_mut(self.0.call_mut(arg))
|
||||
}
|
||||
}
|
||||
impl<F, G, A> Fn1<A> for ChainFn<F, G>
|
||||
where
|
||||
F: Fn1<A>,
|
||||
G: Fn1<F::Output>,
|
||||
{
|
||||
fn call(&self, arg: A) -> Self::Output {
|
||||
self.1.call(self.0.call(arg))
|
||||
}
|
||||
}
|
||||
pub(crate) fn chain_fn<F, G>(f: F, g: G) -> ChainFn<F, G> {
|
||||
ChainFn(f, g)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MergeResultFn;
|
||||
|
||||
impl<T> FnOnce1<Result<T, T>> for MergeResultFn {
|
||||
type Output = T;
|
||||
fn call_once(self, arg: Result<T, T>) -> Self::Output {
|
||||
match arg {
|
||||
Ok(x) => x,
|
||||
Err(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
trivial_fn_impls!(merge_result_fn <> MergeResultFn = "merge_result");
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct InspectFn<F>(F);
|
||||
|
||||
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
||||
impl<F, A> FnOnce1<A> for InspectFn<F>
|
||||
where
|
||||
F: for<'a> FnOnce1<&'a A, Output = ()>,
|
||||
{
|
||||
type Output = A;
|
||||
fn call_once(self, arg: A) -> Self::Output {
|
||||
self.0.call_once(&arg);
|
||||
arg
|
||||
}
|
||||
}
|
||||
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
||||
impl<F, A> FnMut1<A> for InspectFn<F>
|
||||
where
|
||||
F: for<'a> FnMut1<&'a A, Output = ()>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: A) -> Self::Output {
|
||||
self.0.call_mut(&arg);
|
||||
arg
|
||||
}
|
||||
}
|
||||
#[allow(single_use_lifetimes)] // https://github.com/rust-lang/rust/issues/55058
|
||||
impl<F, A> Fn1<A> for InspectFn<F>
|
||||
where
|
||||
F: for<'a> Fn1<&'a A, Output = ()>,
|
||||
{
|
||||
fn call(&self, arg: A) -> Self::Output {
|
||||
self.0.call(&arg);
|
||||
arg
|
||||
}
|
||||
}
|
||||
pub(crate) fn inspect_fn<F>(f: F) -> InspectFn<F> {
|
||||
InspectFn(f)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct MapOkFn<F>(F);
|
||||
|
||||
impl<F, T, E> FnOnce1<Result<T, E>> for MapOkFn<F>
|
||||
where
|
||||
F: FnOnce1<T>,
|
||||
{
|
||||
type Output = Result<F::Output, E>;
|
||||
fn call_once(self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.map(|x| self.0.call_once(x))
|
||||
}
|
||||
}
|
||||
impl<F, T, E> FnMut1<Result<T, E>> for MapOkFn<F>
|
||||
where
|
||||
F: FnMut1<T>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.map(|x| self.0.call_mut(x))
|
||||
}
|
||||
}
|
||||
impl<F, T, E> Fn1<Result<T, E>> for MapOkFn<F>
|
||||
where
|
||||
F: Fn1<T>,
|
||||
{
|
||||
fn call(&self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.map(|x| self.0.call(x))
|
||||
}
|
||||
}
|
||||
pub(crate) fn map_ok_fn<F>(f: F) -> MapOkFn<F> {
|
||||
MapOkFn(f)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct MapErrFn<F>(F);
|
||||
|
||||
impl<F, T, E> FnOnce1<Result<T, E>> for MapErrFn<F>
|
||||
where
|
||||
F: FnOnce1<E>,
|
||||
{
|
||||
type Output = Result<T, F::Output>;
|
||||
fn call_once(self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.map_err(|x| self.0.call_once(x))
|
||||
}
|
||||
}
|
||||
impl<F, T, E> FnMut1<Result<T, E>> for MapErrFn<F>
|
||||
where
|
||||
F: FnMut1<E>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.map_err(|x| self.0.call_mut(x))
|
||||
}
|
||||
}
|
||||
impl<F, T, E> Fn1<Result<T, E>> for MapErrFn<F>
|
||||
where
|
||||
F: Fn1<E>,
|
||||
{
|
||||
fn call(&self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.map_err(|x| self.0.call(x))
|
||||
}
|
||||
}
|
||||
pub(crate) fn map_err_fn<F>(f: F) -> MapErrFn<F> {
|
||||
MapErrFn(f)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct InspectOkFn<F>(F);
|
||||
|
||||
impl<'a, F, T, E> FnOnce1<&'a Result<T, E>> for InspectOkFn<F>
|
||||
where
|
||||
F: FnOnce1<&'a T, Output = ()>,
|
||||
{
|
||||
type Output = ();
|
||||
fn call_once(self, arg: &'a Result<T, E>) -> Self::Output {
|
||||
if let Ok(x) = arg {
|
||||
self.0.call_once(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, F, T, E> FnMut1<&'a Result<T, E>> for InspectOkFn<F>
|
||||
where
|
||||
F: FnMut1<&'a T, Output = ()>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: &'a Result<T, E>) -> Self::Output {
|
||||
if let Ok(x) = arg {
|
||||
self.0.call_mut(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, F, T, E> Fn1<&'a Result<T, E>> for InspectOkFn<F>
|
||||
where
|
||||
F: Fn1<&'a T, Output = ()>,
|
||||
{
|
||||
fn call(&self, arg: &'a Result<T, E>) -> Self::Output {
|
||||
if let Ok(x) = arg {
|
||||
self.0.call(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) fn inspect_ok_fn<F>(f: F) -> InspectOkFn<F> {
|
||||
InspectOkFn(f)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct InspectErrFn<F>(F);
|
||||
|
||||
impl<'a, F, T, E> FnOnce1<&'a Result<T, E>> for InspectErrFn<F>
|
||||
where
|
||||
F: FnOnce1<&'a E, Output = ()>,
|
||||
{
|
||||
type Output = ();
|
||||
fn call_once(self, arg: &'a Result<T, E>) -> Self::Output {
|
||||
if let Err(x) = arg {
|
||||
self.0.call_once(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, F, T, E> FnMut1<&'a Result<T, E>> for InspectErrFn<F>
|
||||
where
|
||||
F: FnMut1<&'a E, Output = ()>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: &'a Result<T, E>) -> Self::Output {
|
||||
if let Err(x) = arg {
|
||||
self.0.call_mut(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, F, T, E> Fn1<&'a Result<T, E>> for InspectErrFn<F>
|
||||
where
|
||||
F: Fn1<&'a E, Output = ()>,
|
||||
{
|
||||
fn call(&self, arg: &'a Result<T, E>) -> Self::Output {
|
||||
if let Err(x) = arg {
|
||||
self.0.call(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) fn inspect_err_fn<F>(f: F) -> InspectErrFn<F> {
|
||||
InspectErrFn(f)
|
||||
}
|
||||
|
||||
pub(crate) type MapOkOrElseFn<F, G> = ChainFn<MapOkFn<F>, ChainFn<MapErrFn<G>, MergeResultFn>>;
|
||||
pub(crate) fn map_ok_or_else_fn<F, G>(f: F, g: G) -> MapOkOrElseFn<F, G> {
|
||||
chain_fn(map_ok_fn(f), chain_fn(map_err_fn(g), merge_result_fn()))
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub struct UnwrapOrElseFn<F>(F);
|
||||
|
||||
impl<F, T, E> FnOnce1<Result<T, E>> for UnwrapOrElseFn<F>
|
||||
where
|
||||
F: FnOnce1<E, Output = T>,
|
||||
{
|
||||
type Output = T;
|
||||
fn call_once(self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.unwrap_or_else(|x| self.0.call_once(x))
|
||||
}
|
||||
}
|
||||
impl<F, T, E> FnMut1<Result<T, E>> for UnwrapOrElseFn<F>
|
||||
where
|
||||
F: FnMut1<E, Output = T>,
|
||||
{
|
||||
fn call_mut(&mut self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.unwrap_or_else(|x| self.0.call_mut(x))
|
||||
}
|
||||
}
|
||||
impl<F, T, E> Fn1<Result<T, E>> for UnwrapOrElseFn<F>
|
||||
where
|
||||
F: Fn1<E, Output = T>,
|
||||
{
|
||||
fn call(&self, arg: Result<T, E>) -> Self::Output {
|
||||
arg.unwrap_or_else(|x| self.0.call(x))
|
||||
}
|
||||
}
|
||||
pub(crate) fn unwrap_or_else_fn<F>(f: F) -> UnwrapOrElseFn<F> {
|
||||
UnwrapOrElseFn(f)
|
||||
}
|
||||
|
||||
pub struct IntoFn<T>(PhantomData<fn() -> T>);
|
||||
|
||||
impl<T> Default for IntoFn<T> {
|
||||
fn default() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
impl<A, T> FnOnce1<A> for IntoFn<T>
|
||||
where
|
||||
A: Into<T>,
|
||||
{
|
||||
type Output = T;
|
||||
fn call_once(self, arg: A) -> Self::Output {
|
||||
arg.into()
|
||||
}
|
||||
}
|
||||
|
||||
trivial_fn_impls!(into_fn <T> IntoFn<T> = "Into::into");
|
||||
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
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
200
zeroidc/vendor/futures-util/src/io/allow_std.rs
vendored
Normal file
200
zeroidc/vendor/futures-util/src/io/allow_std.rs
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, SeekFrom};
|
||||
use std::pin::Pin;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// A simple wrapper type which allows types which implement only
|
||||
/// implement `std::io::Read` or `std::io::Write`
|
||||
/// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`.
|
||||
///
|
||||
/// If these types issue an error with the kind `io::ErrorKind::WouldBlock`,
|
||||
/// it is expected that they will notify the current task on readiness.
|
||||
/// Synchronous `std` types should not issue errors of this kind and
|
||||
/// are safe to use in this context. However, using these types with
|
||||
/// `AllowStdIo` will cause the event loop to block, so they should be used
|
||||
/// with care.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct AllowStdIo<T>(T);
|
||||
|
||||
impl<T> Unpin for AllowStdIo<T> {}
|
||||
|
||||
macro_rules! try_with_interrupt {
|
||||
($e:expr) => {
|
||||
loop {
|
||||
match $e {
|
||||
Ok(e) => {
|
||||
break e;
|
||||
}
|
||||
Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
return Poll::Ready(Err(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<T> AllowStdIo<T> {
|
||||
/// Creates a new `AllowStdIo` from an existing IO object.
|
||||
pub fn new(io: T) -> Self {
|
||||
Self(io)
|
||||
}
|
||||
|
||||
/// Returns a reference to the contained IO object.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the contained IO object.
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Consumes self and returns the contained IO object.
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> io::Write for AllowStdIo<T>
|
||||
where
|
||||
T: io::Write,
|
||||
{
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.0.write_all(buf)
|
||||
}
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
|
||||
self.0.write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncWrite for AllowStdIo<T>
|
||||
where
|
||||
T: io::Write,
|
||||
{
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(try_with_interrupt!(self.0.write(buf))))
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(try_with_interrupt!(self.0.write_vectored(bufs))))
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
try_with_interrupt!(self.0.flush());
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
self.poll_flush(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> io::Read for AllowStdIo<T>
|
||||
where
|
||||
T: io::Read,
|
||||
{
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
self.0.read_to_string(buf)
|
||||
}
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
self.0.read_exact(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncRead for AllowStdIo<T>
|
||||
where
|
||||
T: io::Read,
|
||||
{
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(try_with_interrupt!(self.0.read(buf))))
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(try_with_interrupt!(self.0.read_vectored(bufs))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> io::Seek for AllowStdIo<T>
|
||||
where
|
||||
T: io::Seek,
|
||||
{
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
self.0.seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncSeek for AllowStdIo<T>
|
||||
where
|
||||
T: io::Seek,
|
||||
{
|
||||
fn poll_seek(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
pos: SeekFrom,
|
||||
) -> Poll<io::Result<u64>> {
|
||||
Poll::Ready(Ok(try_with_interrupt!(self.0.seek(pos))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> io::BufRead for AllowStdIo<T>
|
||||
where
|
||||
T: io::BufRead,
|
||||
{
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
self.0.fill_buf()
|
||||
}
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.0.consume(amt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncBufRead for AllowStdIo<T>
|
||||
where
|
||||
T: io::BufRead,
|
||||
{
|
||||
fn poll_fill_buf(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
let this: *mut Self = &mut *self as *mut _;
|
||||
Poll::Ready(Ok(try_with_interrupt!(unsafe { &mut *this }.0.fill_buf())))
|
||||
}
|
||||
|
||||
fn consume(mut self: Pin<&mut Self>, amt: usize) {
|
||||
self.0.consume(amt)
|
||||
}
|
||||
}
|
||||
263
zeroidc/vendor/futures-util/src/io/buf_reader.rs
vendored
Normal file
263
zeroidc/vendor/futures-util/src/io/buf_reader.rs
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
use super::DEFAULT_BUF_SIZE;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSliceMut, SeekFrom};
|
||||
use pin_project_lite::pin_project;
|
||||
use std::io::{self, Read};
|
||||
use std::pin::Pin;
|
||||
use std::{cmp, fmt};
|
||||
|
||||
pin_project! {
|
||||
/// The `BufReader` struct adds buffering to any reader.
|
||||
///
|
||||
/// It can be excessively inefficient to work directly with a [`AsyncRead`]
|
||||
/// instance. A `BufReader` performs large, infrequent reads on the underlying
|
||||
/// [`AsyncRead`] and maintains an in-memory buffer of the results.
|
||||
///
|
||||
/// `BufReader` can improve the speed of programs that make *small* and
|
||||
/// *repeated* read calls to the same file or network socket. It does not
|
||||
/// help when reading very large amounts at once, or reading just one or a few
|
||||
/// times. It also provides no advantage when reading from a source that is
|
||||
/// already in memory, like a `Vec<u8>`.
|
||||
///
|
||||
/// When the `BufReader` is dropped, the contents of its buffer will be
|
||||
/// discarded. Creating multiple instances of a `BufReader` on the same
|
||||
/// stream can cause data loss.
|
||||
///
|
||||
/// [`AsyncRead`]: futures_io::AsyncRead
|
||||
///
|
||||
// TODO: Examples
|
||||
pub struct BufReader<R> {
|
||||
#[pin]
|
||||
inner: R,
|
||||
buffer: Box<[u8]>,
|
||||
pos: usize,
|
||||
cap: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead> BufReader<R> {
|
||||
/// Creates a new `BufReader` with a default buffer capacity. The default is currently 8 KB,
|
||||
/// but may change in the future.
|
||||
pub fn new(inner: R) -> Self {
|
||||
Self::with_capacity(DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `BufReader` with the specified buffer capacity.
|
||||
pub fn with_capacity(capacity: usize, inner: R) -> Self {
|
||||
unsafe {
|
||||
let mut buffer = Vec::with_capacity(capacity);
|
||||
buffer.set_len(capacity);
|
||||
super::initialize(&inner, &mut buffer);
|
||||
Self { inner, buffer: buffer.into_boxed_slice(), pos: 0, cap: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
delegate_access_inner!(inner, R, ());
|
||||
|
||||
/// Returns a reference to the internally buffered data.
|
||||
///
|
||||
/// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buffer[self.pos..self.cap]
|
||||
}
|
||||
|
||||
/// Invalidates all data in the internal buffer.
|
||||
#[inline]
|
||||
fn discard_buffer(self: Pin<&mut Self>) {
|
||||
let this = self.project();
|
||||
*this.pos = 0;
|
||||
*this.cap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + AsyncSeek> BufReader<R> {
|
||||
/// Seeks relative to the current position. If the new position lies within the buffer,
|
||||
/// the buffer will not be flushed, allowing for more efficient seeks.
|
||||
/// This method does not return the location of the underlying reader, so the caller
|
||||
/// must track this information themselves if it is required.
|
||||
pub fn seek_relative(self: Pin<&mut Self>, offset: i64) -> SeeKRelative<'_, R> {
|
||||
SeeKRelative { inner: self, offset, first: true }
|
||||
}
|
||||
|
||||
/// Attempts to seek relative to the current position. If the new position lies within the buffer,
|
||||
/// the buffer will not be flushed, allowing for more efficient seeks.
|
||||
/// This method does not return the location of the underlying reader, so the caller
|
||||
/// must track this information themselves if it is required.
|
||||
pub fn poll_seek_relative(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
offset: i64,
|
||||
) -> Poll<io::Result<()>> {
|
||||
let pos = self.pos as u64;
|
||||
if offset < 0 {
|
||||
if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
|
||||
*self.project().pos = new_pos as usize;
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
} else if let Some(new_pos) = pos.checked_add(offset as u64) {
|
||||
if new_pos <= self.cap as u64 {
|
||||
*self.project().pos = new_pos as usize;
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
}
|
||||
self.poll_seek(cx, SeekFrom::Current(offset)).map(|res| res.map(|_| ()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead> AsyncRead for BufReader<R> {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
// If we don't have any buffered data and we're doing a massive read
|
||||
// (larger than our internal buffer), bypass our internal buffer
|
||||
// entirely.
|
||||
if self.pos == self.cap && buf.len() >= self.buffer.len() {
|
||||
let res = ready!(self.as_mut().project().inner.poll_read(cx, buf));
|
||||
self.discard_buffer();
|
||||
return Poll::Ready(res);
|
||||
}
|
||||
let mut rem = ready!(self.as_mut().poll_fill_buf(cx))?;
|
||||
let nread = rem.read(buf)?;
|
||||
self.consume(nread);
|
||||
Poll::Ready(Ok(nread))
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
|
||||
if self.pos == self.cap && total_len >= self.buffer.len() {
|
||||
let res = ready!(self.as_mut().project().inner.poll_read_vectored(cx, bufs));
|
||||
self.discard_buffer();
|
||||
return Poll::Ready(res);
|
||||
}
|
||||
let mut rem = ready!(self.as_mut().poll_fill_buf(cx))?;
|
||||
let nread = rem.read_vectored(bufs)?;
|
||||
self.consume(nread);
|
||||
Poll::Ready(Ok(nread))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead> AsyncBufRead for BufReader<R> {
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
let this = self.project();
|
||||
|
||||
// If we've reached the end of our internal buffer then we need to fetch
|
||||
// some more data from the underlying reader.
|
||||
// Branch using `>=` instead of the more correct `==`
|
||||
// to tell the compiler that the pos..cap slice is always valid.
|
||||
if *this.pos >= *this.cap {
|
||||
debug_assert!(*this.pos == *this.cap);
|
||||
*this.cap = ready!(this.inner.poll_read(cx, this.buffer))?;
|
||||
*this.pos = 0;
|
||||
}
|
||||
Poll::Ready(Ok(&this.buffer[*this.pos..*this.cap]))
|
||||
}
|
||||
|
||||
fn consume(self: Pin<&mut Self>, amt: usize) {
|
||||
*self.project().pos = cmp::min(self.pos + amt, self.cap);
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncWrite> AsyncWrite for BufReader<R> {
|
||||
delegate_async_write!(inner);
|
||||
}
|
||||
|
||||
impl<R: fmt::Debug> fmt::Debug for BufReader<R> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BufReader")
|
||||
.field("reader", &self.inner)
|
||||
.field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buffer.len()))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + AsyncSeek> AsyncSeek for BufReader<R> {
|
||||
/// Seek to an offset, in bytes, in the underlying reader.
|
||||
///
|
||||
/// The position used for seeking with `SeekFrom::Current(_)` is the
|
||||
/// position the underlying reader would be at if the `BufReader` had no
|
||||
/// internal buffer.
|
||||
///
|
||||
/// Seeking always discards the internal buffer, even if the seek position
|
||||
/// would otherwise fall within it. This guarantees that calling
|
||||
/// `.into_inner()` immediately after a seek yields the underlying reader
|
||||
/// at the same position.
|
||||
///
|
||||
/// To seek without discarding the internal buffer, use
|
||||
/// [`BufReader::seek_relative`](BufReader::seek_relative) or
|
||||
/// [`BufReader::poll_seek_relative`](BufReader::poll_seek_relative).
|
||||
///
|
||||
/// See [`AsyncSeek`](futures_io::AsyncSeek) for more details.
|
||||
///
|
||||
/// Note: In the edge case where you're seeking with `SeekFrom::Current(n)`
|
||||
/// where `n` minus the internal buffer length overflows an `i64`, two
|
||||
/// seeks will be performed instead of one. If the second seek returns
|
||||
/// `Err`, the underlying reader will be left at the same position it would
|
||||
/// have if you called `seek` with `SeekFrom::Current(0)`.
|
||||
fn poll_seek(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
pos: SeekFrom,
|
||||
) -> Poll<io::Result<u64>> {
|
||||
let result: u64;
|
||||
if let SeekFrom::Current(n) = pos {
|
||||
let remainder = (self.cap - self.pos) as i64;
|
||||
// it should be safe to assume that remainder fits within an i64 as the alternative
|
||||
// means we managed to allocate 8 exbibytes and that's absurd.
|
||||
// But it's not out of the realm of possibility for some weird underlying reader to
|
||||
// support seeking by i64::min_value() so we need to handle underflow when subtracting
|
||||
// remainder.
|
||||
if let Some(offset) = n.checked_sub(remainder) {
|
||||
result =
|
||||
ready!(self.as_mut().project().inner.poll_seek(cx, SeekFrom::Current(offset)))?;
|
||||
} else {
|
||||
// seek backwards by our remainder, and then by the offset
|
||||
ready!(self.as_mut().project().inner.poll_seek(cx, SeekFrom::Current(-remainder)))?;
|
||||
self.as_mut().discard_buffer();
|
||||
result = ready!(self.as_mut().project().inner.poll_seek(cx, SeekFrom::Current(n)))?;
|
||||
}
|
||||
} else {
|
||||
// Seeking with Start/End doesn't care about our buffer length.
|
||||
result = ready!(self.as_mut().project().inner.poll_seek(cx, pos))?;
|
||||
}
|
||||
self.discard_buffer();
|
||||
Poll::Ready(Ok(result))
|
||||
}
|
||||
}
|
||||
|
||||
/// Future for the [`BufReader::seek_relative`](self::BufReader::seek_relative) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless polled"]
|
||||
pub struct SeeKRelative<'a, R> {
|
||||
inner: Pin<&'a mut BufReader<R>>,
|
||||
offset: i64,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<R> Future for SeeKRelative<'_, R>
|
||||
where
|
||||
R: AsyncRead + AsyncSeek,
|
||||
{
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let offset = self.offset;
|
||||
if self.first {
|
||||
self.first = false;
|
||||
self.inner.as_mut().poll_seek_relative(cx, offset)
|
||||
} else {
|
||||
self.inner
|
||||
.as_mut()
|
||||
.as_mut()
|
||||
.poll_seek(cx, SeekFrom::Current(offset))
|
||||
.map(|res| res.map(|_| ()))
|
||||
}
|
||||
}
|
||||
}
|
||||
224
zeroidc/vendor/futures-util/src/io/buf_writer.rs
vendored
Normal file
224
zeroidc/vendor/futures-util/src/io/buf_writer.rs
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
use super::DEFAULT_BUF_SIZE;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, SeekFrom};
|
||||
use pin_project_lite::pin_project;
|
||||
use std::fmt;
|
||||
use std::io::{self, Write};
|
||||
use std::pin::Pin;
|
||||
use std::ptr;
|
||||
|
||||
pin_project! {
|
||||
/// Wraps a writer and buffers its output.
|
||||
///
|
||||
/// It can be excessively inefficient to work directly with something that
|
||||
/// implements [`AsyncWrite`]. A `BufWriter` keeps an in-memory buffer of data and
|
||||
/// writes it to an underlying writer in large, infrequent batches.
|
||||
///
|
||||
/// `BufWriter` can improve the speed of programs that make *small* and
|
||||
/// *repeated* write calls to the same file or network socket. It does not
|
||||
/// help when writing very large amounts at once, or writing just one or a few
|
||||
/// times. It also provides no advantage when writing to a destination that is
|
||||
/// in memory, like a `Vec<u8>`.
|
||||
///
|
||||
/// When the `BufWriter` is dropped, the contents of its buffer will be
|
||||
/// discarded. Creating multiple instances of a `BufWriter` on the same
|
||||
/// stream can cause data loss. If you need to write out the contents of its
|
||||
/// buffer, you must manually call flush before the writer is dropped.
|
||||
///
|
||||
/// [`AsyncWrite`]: futures_io::AsyncWrite
|
||||
/// [`flush`]: super::AsyncWriteExt::flush
|
||||
///
|
||||
// TODO: Examples
|
||||
pub struct BufWriter<W> {
|
||||
#[pin]
|
||||
inner: W,
|
||||
buf: Vec<u8>,
|
||||
written: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite> BufWriter<W> {
|
||||
/// Creates a new `BufWriter` with a default buffer capacity. The default is currently 8 KB,
|
||||
/// but may change in the future.
|
||||
pub fn new(inner: W) -> Self {
|
||||
Self::with_capacity(DEFAULT_BUF_SIZE, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `BufWriter` with the specified buffer capacity.
|
||||
pub fn with_capacity(cap: usize, inner: W) -> Self {
|
||||
Self { inner, buf: Vec::with_capacity(cap), written: 0 }
|
||||
}
|
||||
|
||||
pub(super) fn flush_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
let mut this = self.project();
|
||||
|
||||
let len = this.buf.len();
|
||||
let mut ret = Ok(());
|
||||
while *this.written < len {
|
||||
match ready!(this.inner.as_mut().poll_write(cx, &this.buf[*this.written..])) {
|
||||
Ok(0) => {
|
||||
ret = Err(io::Error::new(
|
||||
io::ErrorKind::WriteZero,
|
||||
"failed to write the buffered data",
|
||||
));
|
||||
break;
|
||||
}
|
||||
Ok(n) => *this.written += n,
|
||||
Err(e) => {
|
||||
ret = Err(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if *this.written > 0 {
|
||||
this.buf.drain(..*this.written);
|
||||
}
|
||||
*this.written = 0;
|
||||
Poll::Ready(ret)
|
||||
}
|
||||
|
||||
delegate_access_inner!(inner, W, ());
|
||||
|
||||
/// Returns a reference to the internally buffered data.
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buf
|
||||
}
|
||||
|
||||
/// Capacity of `buf`. how many chars can be held in buffer
|
||||
pub(super) fn capacity(&self) -> usize {
|
||||
self.buf.capacity()
|
||||
}
|
||||
|
||||
/// Remaining number of bytes to reach `buf` 's capacity
|
||||
#[inline]
|
||||
pub(super) fn spare_capacity(&self) -> usize {
|
||||
self.buf.capacity() - self.buf.len()
|
||||
}
|
||||
|
||||
/// Write a byte slice directly into buffer
|
||||
///
|
||||
/// Will truncate the number of bytes written to `spare_capacity()` so you want to
|
||||
/// calculate the size of your slice to avoid losing bytes
|
||||
///
|
||||
/// Based on `std::io::BufWriter`
|
||||
pub(super) fn write_to_buf(self: Pin<&mut Self>, buf: &[u8]) -> usize {
|
||||
let available = self.spare_capacity();
|
||||
let amt_to_buffer = available.min(buf.len());
|
||||
|
||||
// SAFETY: `amt_to_buffer` is <= buffer's spare capacity by construction.
|
||||
unsafe {
|
||||
self.write_to_buffer_unchecked(&buf[..amt_to_buffer]);
|
||||
}
|
||||
|
||||
amt_to_buffer
|
||||
}
|
||||
|
||||
/// Write byte slice directly into `self.buf`
|
||||
///
|
||||
/// Based on `std::io::BufWriter`
|
||||
#[inline]
|
||||
unsafe fn write_to_buffer_unchecked(self: Pin<&mut Self>, buf: &[u8]) {
|
||||
debug_assert!(buf.len() <= self.spare_capacity());
|
||||
let this = self.project();
|
||||
let old_len = this.buf.len();
|
||||
let buf_len = buf.len();
|
||||
let src = buf.as_ptr();
|
||||
let dst = this.buf.as_mut_ptr().add(old_len);
|
||||
ptr::copy_nonoverlapping(src, dst, buf_len);
|
||||
this.buf.set_len(old_len + buf_len);
|
||||
}
|
||||
|
||||
/// Write directly using `inner`, bypassing buffering
|
||||
pub(super) fn inner_poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
self.project().inner.poll_write(cx, buf)
|
||||
}
|
||||
|
||||
/// Write directly using `inner`, bypassing buffering
|
||||
pub(super) fn inner_poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
self.project().inner.poll_write_vectored(cx, bufs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite> AsyncWrite for BufWriter<W> {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
if self.buf.len() + buf.len() > self.buf.capacity() {
|
||||
ready!(self.as_mut().flush_buf(cx))?;
|
||||
}
|
||||
if buf.len() >= self.buf.capacity() {
|
||||
self.project().inner.poll_write(cx, buf)
|
||||
} else {
|
||||
Poll::Ready(self.project().buf.write(buf))
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
|
||||
if self.buf.len() + total_len > self.buf.capacity() {
|
||||
ready!(self.as_mut().flush_buf(cx))?;
|
||||
}
|
||||
if total_len >= self.buf.capacity() {
|
||||
self.project().inner.poll_write_vectored(cx, bufs)
|
||||
} else {
|
||||
Poll::Ready(self.project().buf.write_vectored(bufs))
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
ready!(self.as_mut().flush_buf(cx))?;
|
||||
self.project().inner.poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
ready!(self.as_mut().flush_buf(cx))?;
|
||||
self.project().inner.poll_close(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncRead> AsyncRead for BufWriter<W> {
|
||||
delegate_async_read!(inner);
|
||||
}
|
||||
|
||||
impl<W: AsyncBufRead> AsyncBufRead for BufWriter<W> {
|
||||
delegate_async_buf_read!(inner);
|
||||
}
|
||||
|
||||
impl<W: fmt::Debug> fmt::Debug for BufWriter<W> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("BufWriter")
|
||||
.field("writer", &self.inner)
|
||||
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
|
||||
.field("written", &self.written)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + AsyncSeek> AsyncSeek for BufWriter<W> {
|
||||
/// Seek to the offset, in bytes, in the underlying writer.
|
||||
///
|
||||
/// Seeking always writes out the internal buffer before seeking.
|
||||
fn poll_seek(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
pos: SeekFrom,
|
||||
) -> Poll<io::Result<u64>> {
|
||||
ready!(self.as_mut().flush_buf(cx))?;
|
||||
self.project().inner.poll_seek(cx, pos)
|
||||
}
|
||||
}
|
||||
142
zeroidc/vendor/futures-util/src/io/chain.rs
vendored
Normal file
142
zeroidc/vendor/futures-util/src/io/chain.rs
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncRead, IoSliceMut};
|
||||
use pin_project_lite::pin_project;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
pin_project! {
|
||||
/// Reader for the [`chain`](super::AsyncReadExt::chain) method.
|
||||
#[must_use = "readers do nothing unless polled"]
|
||||
pub struct Chain<T, U> {
|
||||
#[pin]
|
||||
first: T,
|
||||
#[pin]
|
||||
second: U,
|
||||
done_first: bool,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Chain<T, U>
|
||||
where
|
||||
T: AsyncRead,
|
||||
U: AsyncRead,
|
||||
{
|
||||
pub(super) fn new(first: T, second: U) -> Self {
|
||||
Self { first, second, done_first: false }
|
||||
}
|
||||
|
||||
/// Gets references to the underlying readers in this `Chain`.
|
||||
pub fn get_ref(&self) -> (&T, &U) {
|
||||
(&self.first, &self.second)
|
||||
}
|
||||
|
||||
/// Gets mutable references to the underlying readers in this `Chain`.
|
||||
///
|
||||
/// Care should be taken to avoid modifying the internal I/O state of the
|
||||
/// underlying readers as doing so may corrupt the internal state of this
|
||||
/// `Chain`.
|
||||
pub fn get_mut(&mut self) -> (&mut T, &mut U) {
|
||||
(&mut self.first, &mut self.second)
|
||||
}
|
||||
|
||||
/// Gets pinned mutable references to the underlying readers in this `Chain`.
|
||||
///
|
||||
/// Care should be taken to avoid modifying the internal I/O state of the
|
||||
/// underlying readers as doing so may corrupt the internal state of this
|
||||
/// `Chain`.
|
||||
pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut T>, Pin<&mut U>) {
|
||||
let this = self.project();
|
||||
(this.first, this.second)
|
||||
}
|
||||
|
||||
/// Consumes the `Chain`, returning the wrapped readers.
|
||||
pub fn into_inner(self) -> (T, U) {
|
||||
(self.first, self.second)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> fmt::Debug for Chain<T, U>
|
||||
where
|
||||
T: fmt::Debug,
|
||||
U: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Chain")
|
||||
.field("t", &self.first)
|
||||
.field("u", &self.second)
|
||||
.field("done_first", &self.done_first)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> AsyncRead for Chain<T, U>
|
||||
where
|
||||
T: AsyncRead,
|
||||
U: AsyncRead,
|
||||
{
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let this = self.project();
|
||||
|
||||
if !*this.done_first {
|
||||
match ready!(this.first.poll_read(cx, buf)?) {
|
||||
0 if !buf.is_empty() => *this.done_first = true,
|
||||
n => return Poll::Ready(Ok(n)),
|
||||
}
|
||||
}
|
||||
this.second.poll_read(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let this = self.project();
|
||||
|
||||
if !*this.done_first {
|
||||
let n = ready!(this.first.poll_read_vectored(cx, bufs)?);
|
||||
if n == 0 && bufs.iter().any(|b| !b.is_empty()) {
|
||||
*this.done_first = true
|
||||
} else {
|
||||
return Poll::Ready(Ok(n));
|
||||
}
|
||||
}
|
||||
this.second.poll_read_vectored(cx, bufs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> AsyncBufRead for Chain<T, U>
|
||||
where
|
||||
T: AsyncBufRead,
|
||||
U: AsyncBufRead,
|
||||
{
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
let this = self.project();
|
||||
|
||||
if !*this.done_first {
|
||||
match ready!(this.first.poll_fill_buf(cx)?) {
|
||||
buf if buf.is_empty() => {
|
||||
*this.done_first = true;
|
||||
}
|
||||
buf => return Poll::Ready(Ok(buf)),
|
||||
}
|
||||
}
|
||||
this.second.poll_fill_buf(cx)
|
||||
}
|
||||
|
||||
fn consume(self: Pin<&mut Self>, amt: usize) {
|
||||
let this = self.project();
|
||||
|
||||
if !*this.done_first {
|
||||
this.first.consume(amt)
|
||||
} else {
|
||||
this.second.consume(amt)
|
||||
}
|
||||
}
|
||||
}
|
||||
28
zeroidc/vendor/futures-util/src/io/close.rs
vendored
Normal file
28
zeroidc/vendor/futures-util/src/io/close.rs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncWrite;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`close`](super::AsyncWriteExt::close) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Close<'a, W: ?Sized> {
|
||||
writer: &'a mut W,
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Unpin> Unpin for Close<'_, W> {}
|
||||
|
||||
impl<'a, W: AsyncWrite + ?Sized + Unpin> Close<'a, W> {
|
||||
pub(super) fn new(writer: &'a mut W) -> Self {
|
||||
Self { writer }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + ?Sized + Unpin> Future for Close<'_, W> {
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::new(&mut *self.writer).poll_close(cx)
|
||||
}
|
||||
}
|
||||
58
zeroidc/vendor/futures-util/src/io/copy.rs
vendored
Normal file
58
zeroidc/vendor/futures-util/src/io/copy.rs
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
use super::{copy_buf, BufReader, CopyBuf};
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncRead, AsyncWrite};
|
||||
use pin_project_lite::pin_project;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Creates a future which copies all the bytes from one object to another.
|
||||
///
|
||||
/// The returned future will copy all the bytes read from this `AsyncRead` into the
|
||||
/// `writer` specified. This future will only complete once the `reader` has hit
|
||||
/// EOF and all bytes have been written to and flushed from the `writer`
|
||||
/// provided.
|
||||
///
|
||||
/// On success the number of bytes is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncWriteExt, Cursor};
|
||||
///
|
||||
/// let reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut writer = Cursor::new(vec![0u8; 5]);
|
||||
///
|
||||
/// let bytes = io::copy(reader, &mut writer).await?;
|
||||
/// writer.close().await?;
|
||||
///
|
||||
/// assert_eq!(bytes, 4);
|
||||
/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn copy<R, W>(reader: R, writer: &mut W) -> Copy<'_, R, W>
|
||||
where
|
||||
R: AsyncRead,
|
||||
W: AsyncWrite + Unpin + ?Sized,
|
||||
{
|
||||
Copy { inner: copy_buf(BufReader::new(reader), writer) }
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
/// Future for the [`copy()`] function.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Copy<'a, R, W: ?Sized> {
|
||||
#[pin]
|
||||
inner: CopyBuf<'a, BufReader<R>, W>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead, W: AsyncWrite + Unpin + ?Sized> Future for Copy<'_, R, W> {
|
||||
type Output = io::Result<u64>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.project().inner.poll(cx)
|
||||
}
|
||||
}
|
||||
78
zeroidc/vendor/futures-util/src/io/copy_buf.rs
vendored
Normal file
78
zeroidc/vendor/futures-util/src/io/copy_buf.rs
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncWrite};
|
||||
use pin_project_lite::pin_project;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Creates a future which copies all the bytes from one object to another.
|
||||
///
|
||||
/// The returned future will copy all the bytes read from this `AsyncBufRead` into the
|
||||
/// `writer` specified. This future will only complete once the `reader` has hit
|
||||
/// EOF and all bytes have been written to and flushed from the `writer`
|
||||
/// provided.
|
||||
///
|
||||
/// On success the number of bytes is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncWriteExt, Cursor};
|
||||
///
|
||||
/// let reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut writer = Cursor::new(vec![0u8; 5]);
|
||||
///
|
||||
/// let bytes = io::copy_buf(reader, &mut writer).await?;
|
||||
/// writer.close().await?;
|
||||
///
|
||||
/// assert_eq!(bytes, 4);
|
||||
/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn copy_buf<R, W>(reader: R, writer: &mut W) -> CopyBuf<'_, R, W>
|
||||
where
|
||||
R: AsyncBufRead,
|
||||
W: AsyncWrite + Unpin + ?Sized,
|
||||
{
|
||||
CopyBuf { reader, writer, amt: 0 }
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
/// Future for the [`copy_buf()`] function.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct CopyBuf<'a, R, W: ?Sized> {
|
||||
#[pin]
|
||||
reader: R,
|
||||
writer: &'a mut W,
|
||||
amt: u64,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, W> Future for CopyBuf<'_, R, W>
|
||||
where
|
||||
R: AsyncBufRead,
|
||||
W: AsyncWrite + Unpin + ?Sized,
|
||||
{
|
||||
type Output = io::Result<u64>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.project();
|
||||
loop {
|
||||
let buffer = ready!(this.reader.as_mut().poll_fill_buf(cx))?;
|
||||
if buffer.is_empty() {
|
||||
ready!(Pin::new(&mut this.writer).poll_flush(cx))?;
|
||||
return Poll::Ready(Ok(*this.amt));
|
||||
}
|
||||
|
||||
let i = ready!(Pin::new(&mut this.writer).poll_write(cx, buffer))?;
|
||||
if i == 0 {
|
||||
return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
|
||||
}
|
||||
*this.amt += i as u64;
|
||||
this.reader.as_mut().consume(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
240
zeroidc/vendor/futures-util/src/io/cursor.rs
vendored
Normal file
240
zeroidc/vendor/futures-util/src/io/cursor.rs
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
use futures_core::task::{Context, Poll};
|
||||
#[cfg(feature = "read_initializer")]
|
||||
use futures_io::Initializer;
|
||||
use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, IoSlice, IoSliceMut, SeekFrom};
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// A `Cursor` wraps an in-memory buffer and provides it with a
|
||||
/// [`AsyncSeek`] implementation.
|
||||
///
|
||||
/// `Cursor`s are used with in-memory buffers, anything implementing
|
||||
/// `AsRef<[u8]>`, to allow them to implement [`AsyncRead`] and/or [`AsyncWrite`],
|
||||
/// allowing these buffers to be used anywhere you might use a reader or writer
|
||||
/// that does actual I/O.
|
||||
///
|
||||
/// This library implements some I/O traits on various types which
|
||||
/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
|
||||
/// `Cursor<`[`&[u8]`][bytes]`>`.
|
||||
///
|
||||
/// [`AsyncSeek`]: trait.AsyncSeek.html
|
||||
/// [`AsyncRead`]: trait.AsyncRead.html
|
||||
/// [`AsyncWrite`]: trait.AsyncWrite.html
|
||||
/// [bytes]: https://doc.rust-lang.org/std/primitive.slice.html
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Cursor<T> {
|
||||
inner: io::Cursor<T>,
|
||||
}
|
||||
|
||||
impl<T> Cursor<T> {
|
||||
/// Creates a new cursor wrapping the provided underlying in-memory buffer.
|
||||
///
|
||||
/// Cursor initial position is `0` even if underlying buffer (e.g., `Vec`)
|
||||
/// is not empty. So writing to cursor starts with overwriting `Vec`
|
||||
/// content, not with appending to it.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use futures::io::Cursor;
|
||||
///
|
||||
/// let buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
/// ```
|
||||
pub fn new(inner: T) -> Self {
|
||||
Self { inner: io::Cursor::new(inner) }
|
||||
}
|
||||
|
||||
/// Consumes this cursor, returning the underlying value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use futures::io::Cursor;
|
||||
///
|
||||
/// let buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
///
|
||||
/// let vec = buff.into_inner();
|
||||
/// ```
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner.into_inner()
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying value in this cursor.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use futures::io::Cursor;
|
||||
///
|
||||
/// let buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
///
|
||||
/// let reference = buff.get_ref();
|
||||
/// ```
|
||||
pub fn get_ref(&self) -> &T {
|
||||
self.inner.get_ref()
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying value in this cursor.
|
||||
///
|
||||
/// Care should be taken to avoid modifying the internal I/O state of the
|
||||
/// underlying value as it may corrupt this cursor's position.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use futures::io::Cursor;
|
||||
///
|
||||
/// let mut buff = Cursor::new(Vec::new());
|
||||
/// # fn force_inference(_: &Cursor<Vec<u8>>) {}
|
||||
/// # force_inference(&buff);
|
||||
///
|
||||
/// let reference = buff.get_mut();
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
self.inner.get_mut()
|
||||
}
|
||||
|
||||
/// Returns the current position of this cursor.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncSeekExt, Cursor, SeekFrom};
|
||||
///
|
||||
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
|
||||
///
|
||||
/// assert_eq!(buff.position(), 0);
|
||||
///
|
||||
/// buff.seek(SeekFrom::Current(2)).await?;
|
||||
/// assert_eq!(buff.position(), 2);
|
||||
///
|
||||
/// buff.seek(SeekFrom::Current(-1)).await?;
|
||||
/// assert_eq!(buff.position(), 1);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn position(&self) -> u64 {
|
||||
self.inner.position()
|
||||
}
|
||||
|
||||
/// Sets the position of this cursor.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use futures::io::Cursor;
|
||||
///
|
||||
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
|
||||
///
|
||||
/// assert_eq!(buff.position(), 0);
|
||||
///
|
||||
/// buff.set_position(2);
|
||||
/// assert_eq!(buff.position(), 2);
|
||||
///
|
||||
/// buff.set_position(4);
|
||||
/// assert_eq!(buff.position(), 4);
|
||||
/// ```
|
||||
pub fn set_position(&mut self, pos: u64) {
|
||||
self.inner.set_position(pos)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncSeek for Cursor<T>
|
||||
where
|
||||
T: AsRef<[u8]> + Unpin,
|
||||
{
|
||||
fn poll_seek(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
pos: SeekFrom,
|
||||
) -> Poll<io::Result<u64>> {
|
||||
Poll::Ready(io::Seek::seek(&mut self.inner, pos))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]> + Unpin> AsyncRead for Cursor<T> {
|
||||
#[cfg(feature = "read_initializer")]
|
||||
#[inline]
|
||||
unsafe fn initializer(&self) -> Initializer {
|
||||
io::Read::initializer(&self.inner)
|
||||
}
|
||||
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
_cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(io::Read::read(&mut self.inner, buf))
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(io::Read::read_vectored(&mut self.inner, bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncBufRead for Cursor<T>
|
||||
where
|
||||
T: AsRef<[u8]> + Unpin,
|
||||
{
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
Poll::Ready(io::BufRead::fill_buf(&mut self.get_mut().inner))
|
||||
}
|
||||
|
||||
fn consume(mut self: Pin<&mut Self>, amt: usize) {
|
||||
io::BufRead::consume(&mut self.inner, amt)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! delegate_async_write_to_stdio {
|
||||
() => {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(io::Write::write(&mut self.inner, buf))
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(io::Write::write_vectored(&mut self.inner, bufs))
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(io::Write::flush(&mut self.inner))
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
self.poll_flush(cx)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl AsyncWrite for Cursor<&mut [u8]> {
|
||||
delegate_async_write_to_stdio!();
|
||||
}
|
||||
|
||||
impl AsyncWrite for Cursor<&mut Vec<u8>> {
|
||||
delegate_async_write_to_stdio!();
|
||||
}
|
||||
|
||||
impl AsyncWrite for Cursor<Vec<u8>> {
|
||||
delegate_async_write_to_stdio!();
|
||||
}
|
||||
|
||||
impl AsyncWrite for Cursor<Box<[u8]>> {
|
||||
delegate_async_write_to_stdio!();
|
||||
}
|
||||
59
zeroidc/vendor/futures-util/src/io/empty.rs
vendored
Normal file
59
zeroidc/vendor/futures-util/src/io/empty.rs
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncRead};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Reader for the [`empty()`] function.
|
||||
#[must_use = "readers do nothing unless polled"]
|
||||
pub struct Empty {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
/// Constructs a new handle to an empty reader.
|
||||
///
|
||||
/// All reads from the returned reader will return `Poll::Ready(Ok(0))`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A slightly sad example of not reading anything into a buffer:
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// let mut buffer = String::new();
|
||||
/// let mut reader = io::empty();
|
||||
/// reader.read_to_string(&mut buffer).await?;
|
||||
/// assert!(buffer.is_empty());
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn empty() -> Empty {
|
||||
Empty { _priv: () }
|
||||
}
|
||||
|
||||
impl AsyncRead for Empty {
|
||||
#[inline]
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
_: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncBufRead for Empty {
|
||||
#[inline]
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
Poll::Ready(Ok(&[]))
|
||||
}
|
||||
#[inline]
|
||||
fn consume(self: Pin<&mut Self>, _: usize) {}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Empty {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Empty { .. }")
|
||||
}
|
||||
}
|
||||
51
zeroidc/vendor/futures-util/src/io/fill_buf.rs
vendored
Normal file
51
zeroidc/vendor/futures-util/src/io/fill_buf.rs
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncBufRead;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`fill_buf`](super::AsyncBufReadExt::fill_buf) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct FillBuf<'a, R: ?Sized> {
|
||||
reader: Option<&'a mut R>,
|
||||
}
|
||||
|
||||
impl<R: ?Sized> Unpin for FillBuf<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncBufRead + ?Sized + Unpin> FillBuf<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R) -> Self {
|
||||
Self { reader: Some(reader) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R> Future for FillBuf<'a, R>
|
||||
where
|
||||
R: AsyncBufRead + ?Sized + Unpin,
|
||||
{
|
||||
type Output = io::Result<&'a [u8]>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
let reader = this.reader.take().expect("Polled FillBuf after completion");
|
||||
|
||||
match Pin::new(&mut *reader).poll_fill_buf(cx) {
|
||||
// With polonius it is possible to remove this inner match and just have the correct
|
||||
// lifetime of the reference inferred based on which branch is taken
|
||||
Poll::Ready(Ok(_)) => match Pin::new(reader).poll_fill_buf(cx) {
|
||||
Poll::Ready(Ok(slice)) => Poll::Ready(Ok(slice)),
|
||||
Poll::Ready(Err(err)) => {
|
||||
unreachable!("reader indicated readiness but then returned an error: {:?}", err)
|
||||
}
|
||||
Poll::Pending => {
|
||||
unreachable!("reader indicated readiness but then returned pending")
|
||||
}
|
||||
},
|
||||
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
|
||||
Poll::Pending => {
|
||||
this.reader = Some(reader);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
zeroidc/vendor/futures-util/src/io/flush.rs
vendored
Normal file
31
zeroidc/vendor/futures-util/src/io/flush.rs
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncWrite;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`flush`](super::AsyncWriteExt::flush) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Flush<'a, W: ?Sized> {
|
||||
writer: &'a mut W,
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Unpin> Unpin for Flush<'_, W> {}
|
||||
|
||||
impl<'a, W: AsyncWrite + ?Sized + Unpin> Flush<'a, W> {
|
||||
pub(super) fn new(writer: &'a mut W) -> Self {
|
||||
Self { writer }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> Future for Flush<'_, W>
|
||||
where
|
||||
W: AsyncWrite + ?Sized + Unpin,
|
||||
{
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::new(&mut *self.writer).poll_flush(cx)
|
||||
}
|
||||
}
|
||||
82
zeroidc/vendor/futures-util/src/io/into_sink.rs
vendored
Normal file
82
zeroidc/vendor/futures-util/src/io/into_sink.rs
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncWrite;
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Block<Item> {
|
||||
offset: usize,
|
||||
bytes: Item,
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`into_sink`](super::AsyncWriteExt::into_sink) method.
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
pub struct IntoSink<W, Item> {
|
||||
#[pin]
|
||||
writer: W,
|
||||
// An outstanding block for us to push into the underlying writer, along with an offset of how
|
||||
// far into this block we have written already.
|
||||
buffer: Option<Block<Item>>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite, Item: AsRef<[u8]>> IntoSink<W, Item> {
|
||||
pub(super) fn new(writer: W) -> Self {
|
||||
Self { writer, buffer: None }
|
||||
}
|
||||
|
||||
/// If we have an outstanding block in `buffer` attempt to push it into the writer, does _not_
|
||||
/// flush the writer after it succeeds in pushing the block into it.
|
||||
fn poll_flush_buffer(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), io::Error>> {
|
||||
let mut this = self.project();
|
||||
|
||||
if let Some(buffer) = this.buffer {
|
||||
loop {
|
||||
let bytes = buffer.bytes.as_ref();
|
||||
let written = ready!(this.writer.as_mut().poll_write(cx, &bytes[buffer.offset..]))?;
|
||||
buffer.offset += written;
|
||||
if buffer.offset == bytes.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*this.buffer = None;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite, Item: AsRef<[u8]>> Sink<Item> for IntoSink<W, Item> {
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.poll_flush_buffer(cx))?;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
|
||||
debug_assert!(self.buffer.is_none());
|
||||
*self.project().buffer = Some(Block { offset: 0, bytes: item });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll_flush_buffer(cx))?;
|
||||
ready!(self.project().writer.poll_flush(cx))?;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll_flush_buffer(cx))?;
|
||||
ready!(self.project().writer.poll_close(cx))?;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
155
zeroidc/vendor/futures-util/src/io/line_writer.rs
vendored
Normal file
155
zeroidc/vendor/futures-util/src/io/line_writer.rs
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
use super::buf_writer::BufWriter;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncWrite;
|
||||
use futures_io::IoSlice;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
pin_project! {
|
||||
/// Wrap a writer, like [`BufWriter`] does, but prioritizes buffering lines
|
||||
///
|
||||
/// This was written based on `std::io::LineWriter` which goes into further details
|
||||
/// explaining the code.
|
||||
///
|
||||
/// Buffering is actually done using `BufWriter`. This class will leverage `BufWriter`
|
||||
/// to write on-each-line.
|
||||
#[derive(Debug)]
|
||||
pub struct LineWriter<W: AsyncWrite> {
|
||||
#[pin]
|
||||
buf_writer: BufWriter<W>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite> LineWriter<W> {
|
||||
/// Create a new `LineWriter` with default buffer capacity. The default is currently 1KB
|
||||
/// which was taken from `std::io::LineWriter`
|
||||
pub fn new(inner: W) -> LineWriter<W> {
|
||||
LineWriter::with_capacity(1024, inner)
|
||||
}
|
||||
|
||||
/// Creates a new `LineWriter` with the specified buffer capacity.
|
||||
pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
|
||||
LineWriter { buf_writer: BufWriter::with_capacity(capacity, inner) }
|
||||
}
|
||||
|
||||
/// Flush `buf_writer` if last char is "new line"
|
||||
fn flush_if_completed_line(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
let this = self.project();
|
||||
match this.buf_writer.buffer().last().copied() {
|
||||
Some(b'\n') => this.buf_writer.flush_buf(cx),
|
||||
_ => Poll::Ready(Ok(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to `buf_writer`'s internally buffered data.
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
self.buf_writer.buffer()
|
||||
}
|
||||
|
||||
/// Acquires a reference to the underlying sink or stream that this combinator is
|
||||
/// pulling from.
|
||||
pub fn get_ref(&self) -> &W {
|
||||
self.buf_writer.get_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite> AsyncWrite for LineWriter<W> {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let mut this = self.as_mut().project();
|
||||
let newline_index = match memchr::memrchr(b'\n', buf) {
|
||||
None => {
|
||||
ready!(self.as_mut().flush_if_completed_line(cx)?);
|
||||
return self.project().buf_writer.poll_write(cx, buf);
|
||||
}
|
||||
Some(newline_index) => newline_index + 1,
|
||||
};
|
||||
|
||||
ready!(this.buf_writer.as_mut().poll_flush(cx)?);
|
||||
|
||||
let lines = &buf[..newline_index];
|
||||
|
||||
let flushed = { ready!(this.buf_writer.as_mut().inner_poll_write(cx, lines))? };
|
||||
|
||||
if flushed == 0 {
|
||||
return Poll::Ready(Ok(0));
|
||||
}
|
||||
|
||||
let tail = if flushed >= newline_index {
|
||||
&buf[flushed..]
|
||||
} else if newline_index - flushed <= this.buf_writer.capacity() {
|
||||
&buf[flushed..newline_index]
|
||||
} else {
|
||||
let scan_area = &buf[flushed..];
|
||||
let scan_area = &scan_area[..this.buf_writer.capacity()];
|
||||
match memchr::memrchr(b'\n', scan_area) {
|
||||
Some(newline_index) => &scan_area[..newline_index + 1],
|
||||
None => scan_area,
|
||||
}
|
||||
};
|
||||
|
||||
let buffered = this.buf_writer.as_mut().write_to_buf(tail);
|
||||
Poll::Ready(Ok(flushed + buffered))
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let mut this = self.as_mut().project();
|
||||
// `is_write_vectored()` is handled in original code, but not in this crate
|
||||
// see https://github.com/rust-lang/rust/issues/70436
|
||||
|
||||
let last_newline_buf_idx = bufs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.rev()
|
||||
.find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i));
|
||||
let last_newline_buf_idx = match last_newline_buf_idx {
|
||||
None => {
|
||||
ready!(self.as_mut().flush_if_completed_line(cx)?);
|
||||
return self.project().buf_writer.poll_write_vectored(cx, bufs);
|
||||
}
|
||||
Some(i) => i,
|
||||
};
|
||||
|
||||
ready!(this.buf_writer.as_mut().poll_flush(cx)?);
|
||||
|
||||
let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1);
|
||||
|
||||
let flushed = { ready!(this.buf_writer.as_mut().inner_poll_write_vectored(cx, lines))? };
|
||||
if flushed == 0 {
|
||||
return Poll::Ready(Ok(0));
|
||||
}
|
||||
|
||||
let lines_len = lines.iter().map(|buf| buf.len()).sum();
|
||||
if flushed < lines_len {
|
||||
return Poll::Ready(Ok(flushed));
|
||||
}
|
||||
|
||||
let buffered: usize = tail
|
||||
.iter()
|
||||
.filter(|buf| !buf.is_empty())
|
||||
.map(|buf| this.buf_writer.as_mut().write_to_buf(buf))
|
||||
.take_while(|&n| n > 0)
|
||||
.sum();
|
||||
|
||||
Poll::Ready(Ok(flushed + buffered))
|
||||
}
|
||||
|
||||
/// Forward to `buf_writer` 's `BufWriter::poll_flush()`
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
self.as_mut().project().buf_writer.poll_flush(cx)
|
||||
}
|
||||
|
||||
/// Forward to `buf_writer` 's `BufWriter::poll_close()`
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
self.as_mut().project().buf_writer.poll_close(cx)
|
||||
}
|
||||
}
|
||||
47
zeroidc/vendor/futures-util/src/io/lines.rs
vendored
Normal file
47
zeroidc/vendor/futures-util/src/io/lines.rs
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
use super::read_line::read_line_internal;
|
||||
use futures_core::ready;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncBufRead;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
|
||||
pin_project! {
|
||||
/// Stream for the [`lines`](super::AsyncBufReadExt::lines) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "streams do nothing unless polled"]
|
||||
pub struct Lines<R> {
|
||||
#[pin]
|
||||
reader: R,
|
||||
buf: String,
|
||||
bytes: Vec<u8>,
|
||||
read: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncBufRead> Lines<R> {
|
||||
pub(super) fn new(reader: R) -> Self {
|
||||
Self { reader, buf: String::new(), bytes: Vec::new(), read: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncBufRead> Stream for Lines<R> {
|
||||
type Item = io::Result<String>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let this = self.project();
|
||||
let n = ready!(read_line_internal(this.reader, cx, this.buf, this.bytes, this.read))?;
|
||||
if n == 0 && this.buf.is_empty() {
|
||||
return Poll::Ready(None);
|
||||
}
|
||||
if this.buf.ends_with('\n') {
|
||||
this.buf.pop();
|
||||
if this.buf.ends_with('\r') {
|
||||
this.buf.pop();
|
||||
}
|
||||
}
|
||||
Poll::Ready(Some(Ok(mem::replace(this.buf, String::new()))))
|
||||
}
|
||||
}
|
||||
838
zeroidc/vendor/futures-util/src/io/mod.rs
vendored
Normal file
838
zeroidc/vendor/futures-util/src/io/mod.rs
vendored
Normal file
@@ -0,0 +1,838 @@
|
||||
//! Asynchronous I/O.
|
||||
//!
|
||||
//! This module is the asynchronous version of `std::io`. It defines four
|
||||
//! traits, [`AsyncRead`], [`AsyncWrite`], [`AsyncSeek`], and [`AsyncBufRead`],
|
||||
//! which mirror the `Read`, `Write`, `Seek`, and `BufRead` traits of the
|
||||
//! standard library. However, these traits integrate with the asynchronous
|
||||
//! task system, so that if an I/O object isn't ready for reading (or writing),
|
||||
//! the thread is not blocked, and instead the current task is queued to be
|
||||
//! woken when I/O is ready.
|
||||
//!
|
||||
//! In addition, the [`AsyncReadExt`], [`AsyncWriteExt`], [`AsyncSeekExt`], and
|
||||
//! [`AsyncBufReadExt`] extension traits offer a variety of useful combinators
|
||||
//! for operating with asynchronous I/O objects, including ways to work with
|
||||
//! them using futures, streams and sinks.
|
||||
//!
|
||||
//! This module is only available when the `std` feature of this
|
||||
//! library is activated, and it is activated by default.
|
||||
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
use crate::compat::Compat;
|
||||
use crate::future::assert_future;
|
||||
use crate::stream::assert_stream;
|
||||
use std::{pin::Pin, ptr};
|
||||
|
||||
// Re-export some types from `std::io` so that users don't have to deal
|
||||
// with conflicts when `use`ing `futures::io` and `std::io`.
|
||||
#[doc(no_inline)]
|
||||
pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom};
|
||||
|
||||
pub use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite};
|
||||
|
||||
// used by `BufReader` and `BufWriter`
|
||||
// https://github.com/rust-lang/rust/blob/master/src/libstd/sys_common/io.rs#L1
|
||||
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
|
||||
|
||||
/// Initializes a buffer if necessary.
|
||||
///
|
||||
/// A buffer is currently always initialized.
|
||||
#[inline]
|
||||
unsafe fn initialize<R: AsyncRead>(_reader: &R, buf: &mut [u8]) {
|
||||
ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len())
|
||||
}
|
||||
|
||||
mod allow_std;
|
||||
pub use self::allow_std::AllowStdIo;
|
||||
|
||||
mod buf_reader;
|
||||
pub use self::buf_reader::{BufReader, SeeKRelative};
|
||||
|
||||
mod buf_writer;
|
||||
pub use self::buf_writer::BufWriter;
|
||||
|
||||
mod line_writer;
|
||||
pub use self::line_writer::LineWriter;
|
||||
|
||||
mod chain;
|
||||
pub use self::chain::Chain;
|
||||
|
||||
mod close;
|
||||
pub use self::close::Close;
|
||||
|
||||
mod copy;
|
||||
pub use self::copy::{copy, Copy};
|
||||
|
||||
mod copy_buf;
|
||||
pub use self::copy_buf::{copy_buf, CopyBuf};
|
||||
|
||||
mod cursor;
|
||||
pub use self::cursor::Cursor;
|
||||
|
||||
mod empty;
|
||||
pub use self::empty::{empty, Empty};
|
||||
|
||||
mod fill_buf;
|
||||
pub use self::fill_buf::FillBuf;
|
||||
|
||||
mod flush;
|
||||
pub use self::flush::Flush;
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
mod into_sink;
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
pub use self::into_sink::IntoSink;
|
||||
|
||||
mod lines;
|
||||
pub use self::lines::Lines;
|
||||
|
||||
mod read;
|
||||
pub use self::read::Read;
|
||||
|
||||
mod read_vectored;
|
||||
pub use self::read_vectored::ReadVectored;
|
||||
|
||||
mod read_exact;
|
||||
pub use self::read_exact::ReadExact;
|
||||
|
||||
mod read_line;
|
||||
pub use self::read_line::ReadLine;
|
||||
|
||||
mod read_to_end;
|
||||
pub use self::read_to_end::ReadToEnd;
|
||||
|
||||
mod read_to_string;
|
||||
pub use self::read_to_string::ReadToString;
|
||||
|
||||
mod read_until;
|
||||
pub use self::read_until::ReadUntil;
|
||||
|
||||
mod repeat;
|
||||
pub use self::repeat::{repeat, Repeat};
|
||||
|
||||
mod seek;
|
||||
pub use self::seek::Seek;
|
||||
|
||||
mod sink;
|
||||
pub use self::sink::{sink, Sink};
|
||||
|
||||
mod split;
|
||||
pub use self::split::{ReadHalf, ReuniteError, WriteHalf};
|
||||
|
||||
mod take;
|
||||
pub use self::take::Take;
|
||||
|
||||
mod window;
|
||||
pub use self::window::Window;
|
||||
|
||||
mod write;
|
||||
pub use self::write::Write;
|
||||
|
||||
mod write_vectored;
|
||||
pub use self::write_vectored::WriteVectored;
|
||||
|
||||
mod write_all;
|
||||
pub use self::write_all::WriteAll;
|
||||
|
||||
#[cfg(feature = "write-all-vectored")]
|
||||
mod write_all_vectored;
|
||||
#[cfg(feature = "write-all-vectored")]
|
||||
pub use self::write_all_vectored::WriteAllVectored;
|
||||
|
||||
/// An extension trait which adds utility methods to `AsyncRead` types.
|
||||
pub trait AsyncReadExt: AsyncRead {
|
||||
/// Creates an adaptor which will chain this stream with another.
|
||||
///
|
||||
/// The returned `AsyncRead` instance will first read all bytes from this object
|
||||
/// until EOF is encountered. Afterwards the output is equivalent to the
|
||||
/// output of `next`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let reader1 = Cursor::new([1, 2, 3, 4]);
|
||||
/// let reader2 = Cursor::new([5, 6, 7, 8]);
|
||||
///
|
||||
/// let mut reader = reader1.chain(reader2);
|
||||
/// let mut buffer = Vec::new();
|
||||
///
|
||||
/// // read the value into a Vec.
|
||||
/// reader.read_to_end(&mut buffer).await?;
|
||||
/// assert_eq!(buffer, [1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn chain<R>(self, next: R) -> Chain<Self, R>
|
||||
where
|
||||
Self: Sized,
|
||||
R: AsyncRead,
|
||||
{
|
||||
assert_read(Chain::new(self, next))
|
||||
}
|
||||
|
||||
/// Tries to read some bytes directly into the given `buf` in asynchronous
|
||||
/// manner, returning a future type.
|
||||
///
|
||||
/// The returned future will resolve to the number of bytes read once the read
|
||||
/// operation is completed.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let mut reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut output = [0u8; 5];
|
||||
///
|
||||
/// let bytes = reader.read(&mut output[..]).await?;
|
||||
///
|
||||
/// // This is only guaranteed to be 4 because `&[u8]` is a synchronous
|
||||
/// // reader. In a real system you could get anywhere from 1 to
|
||||
/// // `output.len()` bytes in a single read.
|
||||
/// assert_eq!(bytes, 4);
|
||||
/// assert_eq!(output, [1, 2, 3, 4, 0]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(Read::new(self, buf))
|
||||
}
|
||||
|
||||
/// Creates a future which will read from the `AsyncRead` into `bufs` using vectored
|
||||
/// IO operations.
|
||||
///
|
||||
/// The returned future will resolve to the number of bytes read once the read
|
||||
/// operation is completed.
|
||||
fn read_vectored<'a>(&'a mut self, bufs: &'a mut [IoSliceMut<'a>]) -> ReadVectored<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(ReadVectored::new(self, bufs))
|
||||
}
|
||||
|
||||
/// Creates a future which will read exactly enough bytes to fill `buf`,
|
||||
/// returning an error if end of file (EOF) is hit sooner.
|
||||
///
|
||||
/// The returned future will resolve once the read operation is completed.
|
||||
///
|
||||
/// In the case of an error the buffer and the object will be discarded, with
|
||||
/// the error yielded.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let mut reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut output = [0u8; 4];
|
||||
///
|
||||
/// reader.read_exact(&mut output).await?;
|
||||
///
|
||||
/// assert_eq!(output, [1, 2, 3, 4]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// ## EOF is hit before `buf` is filled
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let mut reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut output = [0u8; 5];
|
||||
///
|
||||
/// let result = reader.read_exact(&mut output).await;
|
||||
///
|
||||
/// assert_eq!(result.unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
|
||||
/// # });
|
||||
/// ```
|
||||
fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<()>, _>(ReadExact::new(self, buf))
|
||||
}
|
||||
|
||||
/// Creates a future which will read all the bytes from this `AsyncRead`.
|
||||
///
|
||||
/// On success the total number of bytes read is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let mut reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut output = Vec::with_capacity(4);
|
||||
///
|
||||
/// let bytes = reader.read_to_end(&mut output).await?;
|
||||
///
|
||||
/// assert_eq!(bytes, 4);
|
||||
/// assert_eq!(output, vec![1, 2, 3, 4]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn read_to_end<'a>(&'a mut self, buf: &'a mut Vec<u8>) -> ReadToEnd<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(ReadToEnd::new(self, buf))
|
||||
}
|
||||
|
||||
/// Creates a future which will read all the bytes from this `AsyncRead`.
|
||||
///
|
||||
/// On success the total number of bytes read is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let mut reader = Cursor::new(&b"1234"[..]);
|
||||
/// let mut buffer = String::with_capacity(4);
|
||||
///
|
||||
/// let bytes = reader.read_to_string(&mut buffer).await?;
|
||||
///
|
||||
/// assert_eq!(bytes, 4);
|
||||
/// assert_eq!(buffer, String::from("1234"));
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn read_to_string<'a>(&'a mut self, buf: &'a mut String) -> ReadToString<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(ReadToString::new(self, buf))
|
||||
}
|
||||
|
||||
/// Helper method for splitting this read/write object into two halves.
|
||||
///
|
||||
/// The two halves returned implement the `AsyncRead` and `AsyncWrite`
|
||||
/// traits, respectively.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncReadExt, Cursor};
|
||||
///
|
||||
/// // Note that for `Cursor` the read and write halves share a single
|
||||
/// // seek position. This may or may not be true for other types that
|
||||
/// // implement both `AsyncRead` and `AsyncWrite`.
|
||||
///
|
||||
/// let reader = Cursor::new([1, 2, 3, 4]);
|
||||
/// let mut buffer = Cursor::new(vec![0, 0, 0, 0, 5, 6, 7, 8]);
|
||||
/// let mut writer = Cursor::new(vec![0u8; 5]);
|
||||
///
|
||||
/// {
|
||||
/// let (buffer_reader, mut buffer_writer) = (&mut buffer).split();
|
||||
/// io::copy(reader, &mut buffer_writer).await?;
|
||||
/// io::copy(buffer_reader, &mut writer).await?;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(buffer.into_inner(), [1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
/// assert_eq!(writer.into_inner(), [5, 6, 7, 8, 0]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
|
||||
where
|
||||
Self: AsyncWrite + Sized,
|
||||
{
|
||||
let (r, w) = split::split(self);
|
||||
(assert_read(r), assert_write(w))
|
||||
}
|
||||
|
||||
/// Creates an AsyncRead adapter which will read at most `limit` bytes
|
||||
/// from the underlying reader.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let reader = Cursor::new(&b"12345678"[..]);
|
||||
/// let mut buffer = [0; 5];
|
||||
///
|
||||
/// let mut take = reader.take(4);
|
||||
/// let n = take.read(&mut buffer).await?;
|
||||
///
|
||||
/// assert_eq!(n, 4);
|
||||
/// assert_eq!(&buffer, b"1234\0");
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn take(self, limit: u64) -> Take<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_read(Take::new(self, limit))
|
||||
}
|
||||
|
||||
/// Wraps an [`AsyncRead`] in a compatibility wrapper that allows it to be
|
||||
/// used as a futures 0.1 / tokio-io 0.1 `AsyncRead`. If the wrapped type
|
||||
/// implements [`AsyncWrite`] as well, the result will also implement the
|
||||
/// futures 0.1 / tokio 0.1 `AsyncWrite` trait.
|
||||
///
|
||||
/// Requires the `io-compat` feature to enable.
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
fn compat(self) -> Compat<Self>
|
||||
where
|
||||
Self: Sized + Unpin,
|
||||
{
|
||||
Compat::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}
|
||||
|
||||
/// An extension trait which adds utility methods to `AsyncWrite` types.
|
||||
pub trait AsyncWriteExt: AsyncWrite {
|
||||
/// Creates a future which will entirely flush this `AsyncWrite`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AllowStdIo, AsyncWriteExt};
|
||||
/// use std::io::{BufWriter, Cursor};
|
||||
///
|
||||
/// let mut output = vec![0u8; 5];
|
||||
///
|
||||
/// {
|
||||
/// let writer = Cursor::new(&mut output);
|
||||
/// let mut buffered = AllowStdIo::new(BufWriter::new(writer));
|
||||
/// buffered.write_all(&[1, 2]).await?;
|
||||
/// buffered.write_all(&[3, 4]).await?;
|
||||
/// buffered.flush().await?;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(output, [1, 2, 3, 4, 0]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn flush(&mut self) -> Flush<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<()>, _>(Flush::new(self))
|
||||
}
|
||||
|
||||
/// Creates a future which will entirely close this `AsyncWrite`.
|
||||
fn close(&mut self) -> Close<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<()>, _>(Close::new(self))
|
||||
}
|
||||
|
||||
/// Creates a future which will write bytes from `buf` into the object.
|
||||
///
|
||||
/// The returned future will resolve to the number of bytes written once the write
|
||||
/// operation is completed.
|
||||
fn write<'a>(&'a mut self, buf: &'a [u8]) -> Write<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(Write::new(self, buf))
|
||||
}
|
||||
|
||||
/// Creates a future which will write bytes from `bufs` into the object using vectored
|
||||
/// IO operations.
|
||||
///
|
||||
/// The returned future will resolve to the number of bytes written once the write
|
||||
/// operation is completed.
|
||||
fn write_vectored<'a>(&'a mut self, bufs: &'a [IoSlice<'a>]) -> WriteVectored<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(WriteVectored::new(self, bufs))
|
||||
}
|
||||
|
||||
/// Write data into this object.
|
||||
///
|
||||
/// Creates a future that will write the entire contents of the buffer `buf` into
|
||||
/// this `AsyncWrite`.
|
||||
///
|
||||
/// The returned future will not complete until all the data has been written.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncWriteExt, Cursor};
|
||||
///
|
||||
/// let mut writer = Cursor::new(vec![0u8; 5]);
|
||||
///
|
||||
/// writer.write_all(&[1, 2, 3, 4]).await?;
|
||||
///
|
||||
/// assert_eq!(writer.into_inner(), [1, 2, 3, 4, 0]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn write_all<'a>(&'a mut self, buf: &'a [u8]) -> WriteAll<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<()>, _>(WriteAll::new(self, buf))
|
||||
}
|
||||
|
||||
/// Attempts to write multiple buffers into this writer.
|
||||
///
|
||||
/// Creates a future that will write the entire contents of `bufs` into this
|
||||
/// `AsyncWrite` using [vectored writes].
|
||||
///
|
||||
/// The returned future will not complete until all the data has been
|
||||
/// written.
|
||||
///
|
||||
/// [vectored writes]: std::io::Write::write_vectored
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Unlike `io::Write::write_vectored`, this takes a *mutable* reference to
|
||||
/// a slice of `IoSlice`s, not an immutable one. That's because we need to
|
||||
/// modify the slice to keep track of the bytes already written.
|
||||
///
|
||||
/// Once this futures returns, the contents of `bufs` are unspecified, as
|
||||
/// this depends on how many calls to `write_vectored` were necessary. It is
|
||||
/// best to understand this function as taking ownership of `bufs` and to
|
||||
/// not use `bufs` afterwards. The underlying buffers, to which the
|
||||
/// `IoSlice`s point (but not the `IoSlice`s themselves), are unchanged and
|
||||
/// can be reused.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::AsyncWriteExt;
|
||||
/// use futures_util::io::Cursor;
|
||||
/// use std::io::IoSlice;
|
||||
///
|
||||
/// let mut writer = Cursor::new(Vec::new());
|
||||
/// let bufs = &mut [
|
||||
/// IoSlice::new(&[1]),
|
||||
/// IoSlice::new(&[2, 3]),
|
||||
/// IoSlice::new(&[4, 5, 6]),
|
||||
/// ];
|
||||
///
|
||||
/// writer.write_all_vectored(bufs).await?;
|
||||
/// // Note: the contents of `bufs` is now unspecified, see the Notes section.
|
||||
///
|
||||
/// assert_eq!(writer.into_inner(), &[1, 2, 3, 4, 5, 6]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
#[cfg(feature = "write-all-vectored")]
|
||||
fn write_all_vectored<'a>(
|
||||
&'a mut self,
|
||||
bufs: &'a mut [IoSlice<'a>],
|
||||
) -> WriteAllVectored<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<()>, _>(WriteAllVectored::new(self, bufs))
|
||||
}
|
||||
|
||||
/// Wraps an [`AsyncWrite`] in a compatibility wrapper that allows it to be
|
||||
/// used as a futures 0.1 / tokio-io 0.1 `AsyncWrite`.
|
||||
/// Requires the `io-compat` feature to enable.
|
||||
#[cfg(feature = "io-compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io-compat")))]
|
||||
fn compat_write(self) -> Compat<Self>
|
||||
where
|
||||
Self: Sized + Unpin,
|
||||
{
|
||||
Compat::new(self)
|
||||
}
|
||||
|
||||
/// Allow using an [`AsyncWrite`] as a [`Sink`](futures_sink::Sink)`<Item: AsRef<[u8]>>`.
|
||||
///
|
||||
/// This adapter produces a sink that will write each value passed to it
|
||||
/// into the underlying writer.
|
||||
///
|
||||
/// Note that this function consumes the given writer, returning a wrapped
|
||||
/// version.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::AsyncWriteExt;
|
||||
/// use futures::stream::{self, StreamExt};
|
||||
///
|
||||
/// let stream = stream::iter(vec![Ok([1, 2, 3]), Ok([4, 5, 6])]);
|
||||
///
|
||||
/// let mut writer = vec![];
|
||||
///
|
||||
/// stream.forward((&mut writer).into_sink()).await?;
|
||||
///
|
||||
/// assert_eq!(writer, vec![1, 2, 3, 4, 5, 6]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(())
|
||||
/// # })?;
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(())
|
||||
/// ```
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
fn into_sink<Item: AsRef<[u8]>>(self) -> IntoSink<Self, Item>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
crate::sink::assert_sink::<Item, Error, _>(IntoSink::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + ?Sized> AsyncWriteExt for W {}
|
||||
|
||||
/// An extension trait which adds utility methods to `AsyncSeek` types.
|
||||
pub trait AsyncSeekExt: AsyncSeek {
|
||||
/// Creates a future which will seek an IO object, and then yield the
|
||||
/// new position in the object and the object itself.
|
||||
///
|
||||
/// In the case of an error the buffer and the object will be discarded, with
|
||||
/// the error yielded.
|
||||
fn seek(&mut self, pos: SeekFrom) -> Seek<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<u64>, _>(Seek::new(self, pos))
|
||||
}
|
||||
|
||||
/// Creates a future which will return the current seek position from the
|
||||
/// start of the stream.
|
||||
///
|
||||
/// This is equivalent to `self.seek(SeekFrom::Current(0))`.
|
||||
fn stream_position(&mut self) -> Seek<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
self.seek(SeekFrom::Current(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: AsyncSeek + ?Sized> AsyncSeekExt for S {}
|
||||
|
||||
/// An extension trait which adds utility methods to `AsyncBufRead` types.
|
||||
pub trait AsyncBufReadExt: AsyncBufRead {
|
||||
/// Creates a future which will wait for a non-empty buffer to be available from this I/O
|
||||
/// object or EOF to be reached.
|
||||
///
|
||||
/// This method is the async equivalent to [`BufRead::fill_buf`](std::io::BufRead::fill_buf).
|
||||
///
|
||||
/// ```rust
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::{io::AsyncBufReadExt as _, stream::{iter, TryStreamExt as _}};
|
||||
///
|
||||
/// let mut stream = iter(vec![Ok(vec![1, 2, 3]), Ok(vec![4, 5, 6])]).into_async_read();
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![1, 2, 3]);
|
||||
/// stream.consume_unpin(2);
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![3]);
|
||||
/// stream.consume_unpin(1);
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![4, 5, 6]);
|
||||
/// stream.consume_unpin(3);
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn fill_buf(&mut self) -> FillBuf<'_, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<&[u8]>, _>(FillBuf::new(self))
|
||||
}
|
||||
|
||||
/// A convenience for calling [`AsyncBufRead::consume`] on [`Unpin`] IO types.
|
||||
///
|
||||
/// ```rust
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::{io::AsyncBufReadExt as _, stream::{iter, TryStreamExt as _}};
|
||||
///
|
||||
/// let mut stream = iter(vec![Ok(vec![1, 2, 3])]).into_async_read();
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![1, 2, 3]);
|
||||
/// stream.consume_unpin(2);
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![3]);
|
||||
/// stream.consume_unpin(1);
|
||||
///
|
||||
/// assert_eq!(stream.fill_buf().await?, vec![]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn consume_unpin(&mut self, amt: usize)
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
Pin::new(self).consume(amt)
|
||||
}
|
||||
|
||||
/// Creates a future which will read all the bytes associated with this I/O
|
||||
/// object into `buf` until the delimiter `byte` or EOF is reached.
|
||||
/// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until).
|
||||
///
|
||||
/// This function will read bytes from the underlying stream until the
|
||||
/// delimiter or EOF is found. Once found, all bytes up to, and including,
|
||||
/// the delimiter (if found) will be appended to `buf`.
|
||||
///
|
||||
/// The returned future will resolve to the number of bytes read once the read
|
||||
/// operation is completed.
|
||||
///
|
||||
/// In the case of an error the buffer and the object will be discarded, with
|
||||
/// the error yielded.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncBufReadExt, Cursor};
|
||||
///
|
||||
/// let mut cursor = Cursor::new(b"lorem-ipsum");
|
||||
/// let mut buf = vec![];
|
||||
///
|
||||
/// // cursor is at 'l'
|
||||
/// let num_bytes = cursor.read_until(b'-', &mut buf).await?;
|
||||
/// assert_eq!(num_bytes, 6);
|
||||
/// assert_eq!(buf, b"lorem-");
|
||||
/// buf.clear();
|
||||
///
|
||||
/// // cursor is at 'i'
|
||||
/// let num_bytes = cursor.read_until(b'-', &mut buf).await?;
|
||||
/// assert_eq!(num_bytes, 5);
|
||||
/// assert_eq!(buf, b"ipsum");
|
||||
/// buf.clear();
|
||||
///
|
||||
/// // cursor is at EOF
|
||||
/// let num_bytes = cursor.read_until(b'-', &mut buf).await?;
|
||||
/// assert_eq!(num_bytes, 0);
|
||||
/// assert_eq!(buf, b"");
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(ReadUntil::new(self, byte, buf))
|
||||
}
|
||||
|
||||
/// Creates a future which will read all the bytes associated with this I/O
|
||||
/// object into `buf` until a newline (the 0xA byte) or EOF is reached,
|
||||
/// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line).
|
||||
///
|
||||
/// This function will read bytes from the underlying stream until the
|
||||
/// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
|
||||
/// up to, and including, the delimiter (if found) will be appended to
|
||||
/// `buf`.
|
||||
///
|
||||
/// The returned future will resolve to the number of bytes read once the read
|
||||
/// operation is completed.
|
||||
///
|
||||
/// In the case of an error the buffer and the object will be discarded, with
|
||||
/// the error yielded.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function has the same error semantics as [`read_until`] and will
|
||||
/// also return an error if the read bytes are not valid UTF-8. If an I/O
|
||||
/// error is encountered then `buf` may contain some bytes already read in
|
||||
/// the event that all data read so far was valid UTF-8.
|
||||
///
|
||||
/// [`read_until`]: AsyncBufReadExt::read_until
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncBufReadExt, Cursor};
|
||||
///
|
||||
/// let mut cursor = Cursor::new(b"foo\nbar");
|
||||
/// let mut buf = String::new();
|
||||
///
|
||||
/// // cursor is at 'f'
|
||||
/// let num_bytes = cursor.read_line(&mut buf).await?;
|
||||
/// assert_eq!(num_bytes, 4);
|
||||
/// assert_eq!(buf, "foo\n");
|
||||
/// buf.clear();
|
||||
///
|
||||
/// // cursor is at 'b'
|
||||
/// let num_bytes = cursor.read_line(&mut buf).await?;
|
||||
/// assert_eq!(num_bytes, 3);
|
||||
/// assert_eq!(buf, "bar");
|
||||
/// buf.clear();
|
||||
///
|
||||
/// // cursor is at EOF
|
||||
/// let num_bytes = cursor.read_line(&mut buf).await?;
|
||||
/// assert_eq!(num_bytes, 0);
|
||||
/// assert_eq!(buf, "");
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<usize>, _>(ReadLine::new(self, buf))
|
||||
}
|
||||
|
||||
/// Returns a stream over the lines of this reader.
|
||||
/// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
|
||||
///
|
||||
/// The stream returned from this function will yield instances of
|
||||
/// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
|
||||
/// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
|
||||
///
|
||||
/// [`io::Result`]: std::io::Result
|
||||
/// [`String`]: String
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
|
||||
///
|
||||
/// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncBufReadExt, Cursor};
|
||||
/// use futures::stream::StreamExt;
|
||||
///
|
||||
/// let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
|
||||
///
|
||||
/// let mut lines_stream = cursor.lines().map(|l| l.unwrap());
|
||||
/// assert_eq!(lines_stream.next().await, Some(String::from("lorem")));
|
||||
/// assert_eq!(lines_stream.next().await, Some(String::from("ipsum")));
|
||||
/// assert_eq!(lines_stream.next().await, Some(String::from("dolor")));
|
||||
/// assert_eq!(lines_stream.next().await, None);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
fn lines(self) -> Lines<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_stream::<Result<String>, _>(Lines::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
|
||||
|
||||
// Just a helper function to ensure the reader we're returning all have the
|
||||
// right implementations.
|
||||
pub(crate) fn assert_read<R>(reader: R) -> R
|
||||
where
|
||||
R: AsyncRead,
|
||||
{
|
||||
reader
|
||||
}
|
||||
// Just a helper function to ensure the writer we're returning all have the
|
||||
// right implementations.
|
||||
pub(crate) fn assert_write<W>(writer: W) -> W
|
||||
where
|
||||
W: AsyncWrite,
|
||||
{
|
||||
writer
|
||||
}
|
||||
30
zeroidc/vendor/futures-util/src/io/read.rs
vendored
Normal file
30
zeroidc/vendor/futures-util/src/io/read.rs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
use crate::io::AsyncRead;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`read`](super::AsyncReadExt::read) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Read<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut [u8],
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for Read<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncRead + ?Sized + Unpin> Read<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self {
|
||||
Self { reader, buf }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + ?Sized + Unpin> Future for Read<'_, R> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
Pin::new(&mut this.reader).poll_read(cx, this.buf)
|
||||
}
|
||||
}
|
||||
42
zeroidc/vendor/futures-util/src/io/read_exact.rs
vendored
Normal file
42
zeroidc/vendor/futures-util/src/io/read_exact.rs
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
use crate::io::AsyncRead;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`read_exact`](super::AsyncReadExt::read_exact) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct ReadExact<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut [u8],
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for ReadExact<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncRead + ?Sized + Unpin> ReadExact<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, buf: &'a mut [u8]) -> Self {
|
||||
Self { reader, buf }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + ?Sized + Unpin> Future for ReadExact<'_, R> {
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
while !this.buf.is_empty() {
|
||||
let n = ready!(Pin::new(&mut this.reader).poll_read(cx, this.buf))?;
|
||||
{
|
||||
let (_, rest) = mem::replace(&mut this.buf, &mut []).split_at_mut(n);
|
||||
this.buf = rest;
|
||||
}
|
||||
if n == 0 {
|
||||
return Poll::Ready(Err(io::ErrorKind::UnexpectedEof.into()));
|
||||
}
|
||||
}
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
57
zeroidc/vendor/futures-util/src/io/read_line.rs
vendored
Normal file
57
zeroidc/vendor/futures-util/src/io/read_line.rs
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
use super::read_until::read_until_internal;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncBufRead;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
use std::str;
|
||||
|
||||
/// Future for the [`read_line`](super::AsyncBufReadExt::read_line) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct ReadLine<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut String,
|
||||
bytes: Vec<u8>,
|
||||
read: usize,
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for ReadLine<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadLine<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, buf: &'a mut String) -> Self {
|
||||
Self { reader, bytes: mem::replace(buf, String::new()).into_bytes(), buf, read: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn read_line_internal<R: AsyncBufRead + ?Sized>(
|
||||
reader: Pin<&mut R>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut String,
|
||||
bytes: &mut Vec<u8>,
|
||||
read: &mut usize,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let ret = ready!(read_until_internal(reader, cx, b'\n', bytes, read));
|
||||
if str::from_utf8(bytes).is_err() {
|
||||
Poll::Ready(ret.and_then(|_| {
|
||||
Err(io::Error::new(io::ErrorKind::InvalidData, "stream did not contain valid UTF-8"))
|
||||
}))
|
||||
} else {
|
||||
debug_assert!(buf.is_empty());
|
||||
debug_assert_eq!(*read, 0);
|
||||
// Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`.
|
||||
mem::swap(unsafe { buf.as_mut_vec() }, bytes);
|
||||
Poll::Ready(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncBufRead + ?Sized + Unpin> Future for ReadLine<'_, R> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let Self { reader, buf, bytes, read } = &mut *self;
|
||||
read_line_internal(Pin::new(reader), cx, buf, bytes, read)
|
||||
}
|
||||
}
|
||||
91
zeroidc/vendor/futures-util/src/io/read_to_end.rs
vendored
Normal file
91
zeroidc/vendor/futures-util/src/io/read_to_end.rs
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncRead;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::vec::Vec;
|
||||
|
||||
/// Future for the [`read_to_end`](super::AsyncReadExt::read_to_end) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct ReadToEnd<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut Vec<u8>,
|
||||
start_len: usize,
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for ReadToEnd<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncRead + ?Sized + Unpin> ReadToEnd<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, buf: &'a mut Vec<u8>) -> Self {
|
||||
let start_len = buf.len();
|
||||
Self { reader, buf, start_len }
|
||||
}
|
||||
}
|
||||
|
||||
struct Guard<'a> {
|
||||
buf: &'a mut Vec<u8>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl Drop for Guard<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.buf.set_len(self.len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This uses an adaptive system to extend the vector when it fills. We want to
|
||||
// avoid paying to allocate and zero a huge chunk of memory if the reader only
|
||||
// has 4 bytes while still making large reads if the reader does have a ton
|
||||
// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
|
||||
// time is 4,500 times (!) slower than this if the reader has a very small
|
||||
// amount of data to return.
|
||||
//
|
||||
// Because we're extending the buffer with uninitialized data for trusted
|
||||
// readers, we need to make sure to truncate that if any of this panics.
|
||||
pub(super) fn read_to_end_internal<R: AsyncRead + ?Sized>(
|
||||
mut rd: Pin<&mut R>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut Vec<u8>,
|
||||
start_len: usize,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let mut g = Guard { len: buf.len(), buf };
|
||||
loop {
|
||||
if g.len == g.buf.len() {
|
||||
unsafe {
|
||||
g.buf.reserve(32);
|
||||
let capacity = g.buf.capacity();
|
||||
g.buf.set_len(capacity);
|
||||
super::initialize(&rd, &mut g.buf[g.len..]);
|
||||
}
|
||||
}
|
||||
|
||||
let buf = &mut g.buf[g.len..];
|
||||
match ready!(rd.as_mut().poll_read(cx, buf)) {
|
||||
Ok(0) => return Poll::Ready(Ok(g.len - start_len)),
|
||||
Ok(n) => {
|
||||
// We can't allow bogus values from read. If it is too large, the returned vec could have its length
|
||||
// set past its capacity, or if it overflows the vec could be shortened which could create an invalid
|
||||
// string if this is called via read_to_string.
|
||||
assert!(n <= buf.len());
|
||||
g.len += n;
|
||||
}
|
||||
Err(e) => return Poll::Ready(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> Future for ReadToEnd<'_, A>
|
||||
where
|
||||
A: AsyncRead + ?Sized + Unpin,
|
||||
{
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
read_to_end_internal(Pin::new(&mut this.reader), cx, this.buf, this.start_len)
|
||||
}
|
||||
}
|
||||
59
zeroidc/vendor/futures-util/src/io/read_to_string.rs
vendored
Normal file
59
zeroidc/vendor/futures-util/src/io/read_to_string.rs
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
use super::read_to_end::read_to_end_internal;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncRead;
|
||||
use std::pin::Pin;
|
||||
use std::vec::Vec;
|
||||
use std::{io, mem, str};
|
||||
|
||||
/// Future for the [`read_to_string`](super::AsyncReadExt::read_to_string) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct ReadToString<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
buf: &'a mut String,
|
||||
bytes: Vec<u8>,
|
||||
start_len: usize,
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for ReadToString<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncRead + ?Sized + Unpin> ReadToString<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, buf: &'a mut String) -> Self {
|
||||
let start_len = buf.len();
|
||||
Self { reader, bytes: mem::replace(buf, String::new()).into_bytes(), buf, start_len }
|
||||
}
|
||||
}
|
||||
|
||||
fn read_to_string_internal<R: AsyncRead + ?Sized>(
|
||||
reader: Pin<&mut R>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut String,
|
||||
bytes: &mut Vec<u8>,
|
||||
start_len: usize,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let ret = ready!(read_to_end_internal(reader, cx, bytes, start_len));
|
||||
if str::from_utf8(bytes).is_err() {
|
||||
Poll::Ready(ret.and_then(|_| {
|
||||
Err(io::Error::new(io::ErrorKind::InvalidData, "stream did not contain valid UTF-8"))
|
||||
}))
|
||||
} else {
|
||||
debug_assert!(buf.is_empty());
|
||||
// Safety: `bytes` is a valid UTF-8 because `str::from_utf8` returned `Ok`.
|
||||
mem::swap(unsafe { buf.as_mut_vec() }, bytes);
|
||||
Poll::Ready(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> Future for ReadToString<'_, A>
|
||||
where
|
||||
A: AsyncRead + ?Sized + Unpin,
|
||||
{
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let Self { reader, buf, bytes, start_len } = &mut *self;
|
||||
read_to_string_internal(Pin::new(reader), cx, buf, bytes, *start_len)
|
||||
}
|
||||
}
|
||||
60
zeroidc/vendor/futures-util/src/io/read_until.rs
vendored
Normal file
60
zeroidc/vendor/futures-util/src/io/read_until.rs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncBufRead;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`read_until`](super::AsyncBufReadExt::read_until) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct ReadUntil<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
byte: u8,
|
||||
buf: &'a mut Vec<u8>,
|
||||
read: usize,
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for ReadUntil<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncBufRead + ?Sized + Unpin> ReadUntil<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, byte: u8, buf: &'a mut Vec<u8>) -> Self {
|
||||
Self { reader, byte, buf, read: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn read_until_internal<R: AsyncBufRead + ?Sized>(
|
||||
mut reader: Pin<&mut R>,
|
||||
cx: &mut Context<'_>,
|
||||
byte: u8,
|
||||
buf: &mut Vec<u8>,
|
||||
read: &mut usize,
|
||||
) -> Poll<io::Result<usize>> {
|
||||
loop {
|
||||
let (done, used) = {
|
||||
let available = ready!(reader.as_mut().poll_fill_buf(cx))?;
|
||||
if let Some(i) = memchr::memchr(byte, available) {
|
||||
buf.extend_from_slice(&available[..=i]);
|
||||
(true, i + 1)
|
||||
} else {
|
||||
buf.extend_from_slice(available);
|
||||
(false, available.len())
|
||||
}
|
||||
};
|
||||
reader.as_mut().consume(used);
|
||||
*read += used;
|
||||
if done || used == 0 {
|
||||
return Poll::Ready(Ok(mem::replace(read, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncBufRead + ?Sized + Unpin> Future for ReadUntil<'_, R> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let Self { reader, byte, buf, read } = &mut *self;
|
||||
read_until_internal(Pin::new(reader), cx, *byte, buf, read)
|
||||
}
|
||||
}
|
||||
30
zeroidc/vendor/futures-util/src/io/read_vectored.rs
vendored
Normal file
30
zeroidc/vendor/futures-util/src/io/read_vectored.rs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
use crate::io::AsyncRead;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use std::io::{self, IoSliceMut};
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`read_vectored`](super::AsyncReadExt::read_vectored) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct ReadVectored<'a, R: ?Sized> {
|
||||
reader: &'a mut R,
|
||||
bufs: &'a mut [IoSliceMut<'a>],
|
||||
}
|
||||
|
||||
impl<R: ?Sized + Unpin> Unpin for ReadVectored<'_, R> {}
|
||||
|
||||
impl<'a, R: AsyncRead + ?Sized + Unpin> ReadVectored<'a, R> {
|
||||
pub(super) fn new(reader: &'a mut R, bufs: &'a mut [IoSliceMut<'a>]) -> Self {
|
||||
Self { reader, bufs }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead + ?Sized + Unpin> Future for ReadVectored<'_, R> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
Pin::new(&mut this.reader).poll_read_vectored(cx, this.bufs)
|
||||
}
|
||||
}
|
||||
66
zeroidc/vendor/futures-util/src/io/repeat.rs
vendored
Normal file
66
zeroidc/vendor/futures-util/src/io/repeat.rs
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncRead, IoSliceMut};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Reader for the [`repeat()`] function.
|
||||
#[must_use = "readers do nothing unless polled"]
|
||||
pub struct Repeat {
|
||||
byte: u8,
|
||||
}
|
||||
|
||||
/// Creates an instance of a reader that infinitely repeats one byte.
|
||||
///
|
||||
/// All reads from this reader will succeed by filling the specified buffer with
|
||||
/// the given byte.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// let mut buffer = [0; 3];
|
||||
/// let mut reader = io::repeat(0b101);
|
||||
/// reader.read_exact(&mut buffer).await.unwrap();
|
||||
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn repeat(byte: u8) -> Repeat {
|
||||
Repeat { byte }
|
||||
}
|
||||
|
||||
impl AsyncRead for Repeat {
|
||||
#[inline]
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
for slot in &mut *buf {
|
||||
*slot = self.byte;
|
||||
}
|
||||
Poll::Ready(Ok(buf.len()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_read_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let mut nwritten = 0;
|
||||
for buf in bufs {
|
||||
nwritten += ready!(self.as_mut().poll_read(cx, buf))?;
|
||||
}
|
||||
Poll::Ready(Ok(nwritten))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Repeat {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Repeat { .. }")
|
||||
}
|
||||
}
|
||||
30
zeroidc/vendor/futures-util/src/io/seek.rs
vendored
Normal file
30
zeroidc/vendor/futures-util/src/io/seek.rs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
use crate::io::{AsyncSeek, SeekFrom};
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`seek`](crate::io::AsyncSeekExt::seek) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Seek<'a, S: ?Sized> {
|
||||
seek: &'a mut S,
|
||||
pos: SeekFrom,
|
||||
}
|
||||
|
||||
impl<S: ?Sized + Unpin> Unpin for Seek<'_, S> {}
|
||||
|
||||
impl<'a, S: AsyncSeek + ?Sized + Unpin> Seek<'a, S> {
|
||||
pub(super) fn new(seek: &'a mut S, pos: SeekFrom) -> Self {
|
||||
Self { seek, pos }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: AsyncSeek + ?Sized + Unpin> Future for Seek<'_, S> {
|
||||
type Output = io::Result<u64>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
Pin::new(&mut this.seek).poll_seek(cx, this.pos)
|
||||
}
|
||||
}
|
||||
67
zeroidc/vendor/futures-util/src/io/sink.rs
vendored
Normal file
67
zeroidc/vendor/futures-util/src/io/sink.rs
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncWrite, IoSlice};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Writer for the [`sink()`] function.
|
||||
#[must_use = "writers do nothing unless polled"]
|
||||
pub struct Sink {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
/// Creates an instance of a writer which will successfully consume all data.
|
||||
///
|
||||
/// All calls to `poll_write` on the returned instance will return `Poll::Ready(Ok(buf.len()))`
|
||||
/// and the contents of the buffer will not be inspected.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// let buffer = vec![1, 2, 3, 5, 8];
|
||||
/// let mut writer = io::sink();
|
||||
/// let num_bytes = writer.write(&buffer).await?;
|
||||
/// assert_eq!(num_bytes, 5);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn sink() -> Sink {
|
||||
Sink { _priv: () }
|
||||
}
|
||||
|
||||
impl AsyncWrite for Sink {
|
||||
#[inline]
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(buf.len()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
_: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
Poll::Ready(Ok(bufs.iter().map(|b| b.len()).sum()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
#[inline]
|
||||
fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Sink {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Sink { .. }")
|
||||
}
|
||||
}
|
||||
115
zeroidc/vendor/futures-util/src/io/split.rs
vendored
Normal file
115
zeroidc/vendor/futures-util/src/io/split.rs
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
use crate::lock::BiLock;
|
||||
use core::fmt;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncRead, AsyncWrite, IoSlice, IoSliceMut};
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// The readable half of an object returned from `AsyncRead::split`.
|
||||
#[derive(Debug)]
|
||||
pub struct ReadHalf<T> {
|
||||
handle: BiLock<T>,
|
||||
}
|
||||
|
||||
/// The writable half of an object returned from `AsyncRead::split`.
|
||||
#[derive(Debug)]
|
||||
pub struct WriteHalf<T> {
|
||||
handle: BiLock<T>,
|
||||
}
|
||||
|
||||
fn lock_and_then<T, U, E, F>(lock: &BiLock<T>, cx: &mut Context<'_>, f: F) -> Poll<Result<U, E>>
|
||||
where
|
||||
F: FnOnce(Pin<&mut T>, &mut Context<'_>) -> Poll<Result<U, E>>,
|
||||
{
|
||||
let mut l = ready!(lock.poll_lock(cx));
|
||||
f(l.as_pin_mut(), cx)
|
||||
}
|
||||
|
||||
pub(super) fn split<T: AsyncRead + AsyncWrite>(t: T) -> (ReadHalf<T>, WriteHalf<T>) {
|
||||
let (a, b) = BiLock::new(t);
|
||||
(ReadHalf { handle: a }, WriteHalf { handle: b })
|
||||
}
|
||||
|
||||
impl<T: Unpin> ReadHalf<T> {
|
||||
/// Attempts to put the two "halves" of a split `AsyncRead + AsyncWrite` back
|
||||
/// together. Succeeds only if the `ReadHalf<T>` and `WriteHalf<T>` are
|
||||
/// a matching pair originating from the same call to `AsyncReadExt::split`.
|
||||
pub fn reunite(self, other: WriteHalf<T>) -> Result<T, ReuniteError<T>> {
|
||||
self.handle
|
||||
.reunite(other.handle)
|
||||
.map_err(|err| ReuniteError(ReadHalf { handle: err.0 }, WriteHalf { handle: err.1 }))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unpin> WriteHalf<T> {
|
||||
/// Attempts to put the two "halves" of a split `AsyncRead + AsyncWrite` back
|
||||
/// together. Succeeds only if the `ReadHalf<T>` and `WriteHalf<T>` are
|
||||
/// a matching pair originating from the same call to `AsyncReadExt::split`.
|
||||
pub fn reunite(self, other: ReadHalf<T>) -> Result<T, ReuniteError<T>> {
|
||||
other.reunite(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead> AsyncRead for ReadHalf<R> {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
lock_and_then(&self.handle, cx, |l, cx| l.poll_read(cx, buf))
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &mut [IoSliceMut<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
lock_and_then(&self.handle, cx, |l, cx| l.poll_read_vectored(cx, bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite> AsyncWrite for WriteHalf<W> {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
lock_and_then(&self.handle, cx, |l, cx| l.poll_write(cx, buf))
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
lock_and_then(&self.handle, cx, |l, cx| l.poll_write_vectored(cx, bufs))
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
lock_and_then(&self.handle, cx, |l, cx| l.poll_flush(cx))
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
lock_and_then(&self.handle, cx, |l, cx| l.poll_close(cx))
|
||||
}
|
||||
}
|
||||
|
||||
/// Error indicating a `ReadHalf<T>` and `WriteHalf<T>` were not two halves
|
||||
/// of a `AsyncRead + AsyncWrite`, and thus could not be `reunite`d.
|
||||
pub struct ReuniteError<T>(pub ReadHalf<T>, pub WriteHalf<T>);
|
||||
|
||||
impl<T> fmt::Debug for ReuniteError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("ReuniteError").field(&"...").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Display for ReuniteError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "tried to reunite a ReadHalf and WriteHalf that don't form a pair")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: core::any::Any> std::error::Error for ReuniteError<T> {}
|
||||
125
zeroidc/vendor/futures-util/src/io/take.rs
vendored
Normal file
125
zeroidc/vendor/futures-util/src/io/take.rs
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::{AsyncBufRead, AsyncRead};
|
||||
use pin_project_lite::pin_project;
|
||||
use std::pin::Pin;
|
||||
use std::{cmp, io};
|
||||
|
||||
pin_project! {
|
||||
/// Reader for the [`take`](super::AsyncReadExt::take) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "readers do nothing unless you `.await` or poll them"]
|
||||
pub struct Take<R> {
|
||||
#[pin]
|
||||
inner: R,
|
||||
limit: u64,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncRead> Take<R> {
|
||||
pub(super) fn new(inner: R, limit: u64) -> Self {
|
||||
Self { inner, limit }
|
||||
}
|
||||
|
||||
/// Returns the remaining number of bytes that can be
|
||||
/// read before this instance will return EOF.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This instance may reach `EOF` after reading fewer bytes than indicated by
|
||||
/// this method if the underlying [`AsyncRead`] instance reaches EOF.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let reader = Cursor::new(&b"12345678"[..]);
|
||||
/// let mut buffer = [0; 2];
|
||||
///
|
||||
/// let mut take = reader.take(4);
|
||||
/// let n = take.read(&mut buffer).await?;
|
||||
///
|
||||
/// assert_eq!(take.limit(), 2);
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn limit(&self) -> u64 {
|
||||
self.limit
|
||||
}
|
||||
|
||||
/// Sets the number of bytes that can be read before this instance will
|
||||
/// return EOF. This is the same as constructing a new `Take` instance, so
|
||||
/// the amount of bytes read and the previous limit value don't matter when
|
||||
/// calling this method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::io::{AsyncReadExt, Cursor};
|
||||
///
|
||||
/// let reader = Cursor::new(&b"12345678"[..]);
|
||||
/// let mut buffer = [0; 4];
|
||||
///
|
||||
/// let mut take = reader.take(4);
|
||||
/// let n = take.read(&mut buffer).await?;
|
||||
///
|
||||
/// assert_eq!(n, 4);
|
||||
/// assert_eq!(take.limit(), 0);
|
||||
///
|
||||
/// take.set_limit(10);
|
||||
/// let n = take.read(&mut buffer).await?;
|
||||
/// assert_eq!(n, 4);
|
||||
///
|
||||
/// # Ok::<(), Box<dyn std::error::Error>>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn set_limit(&mut self, limit: u64) {
|
||||
self.limit = limit
|
||||
}
|
||||
|
||||
delegate_access_inner!(inner, R, ());
|
||||
}
|
||||
|
||||
impl<R: AsyncRead> AsyncRead for Take<R> {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
let this = self.project();
|
||||
|
||||
if *this.limit == 0 {
|
||||
return Poll::Ready(Ok(0));
|
||||
}
|
||||
|
||||
let max = cmp::min(buf.len() as u64, *this.limit) as usize;
|
||||
let n = ready!(this.inner.poll_read(cx, &mut buf[..max]))?;
|
||||
*this.limit -= n as u64;
|
||||
Poll::Ready(Ok(n))
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: AsyncBufRead> AsyncBufRead for Take<R> {
|
||||
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
|
||||
let this = self.project();
|
||||
|
||||
// Don't call into inner reader at all at EOF because it may still block
|
||||
if *this.limit == 0 {
|
||||
return Poll::Ready(Ok(&[]));
|
||||
}
|
||||
|
||||
let buf = ready!(this.inner.poll_fill_buf(cx)?);
|
||||
let cap = cmp::min(buf.len() as u64, *this.limit) as usize;
|
||||
Poll::Ready(Ok(&buf[..cap]))
|
||||
}
|
||||
|
||||
fn consume(self: Pin<&mut Self>, amt: usize) {
|
||||
let this = self.project();
|
||||
|
||||
// Don't let callers reset the limit by passing an overlarge value
|
||||
let amt = cmp::min(amt as u64, *this.limit) as usize;
|
||||
*this.limit -= amt as u64;
|
||||
this.inner.consume(amt);
|
||||
}
|
||||
}
|
||||
104
zeroidc/vendor/futures-util/src/io/window.rs
vendored
Normal file
104
zeroidc/vendor/futures-util/src/io/window.rs
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
use std::ops::{Bound, Range, RangeBounds};
|
||||
|
||||
/// A owned window around an underlying buffer.
|
||||
///
|
||||
/// Normally slices work great for considering sub-portions of a buffer, but
|
||||
/// unfortunately a slice is a *borrowed* type in Rust which has an associated
|
||||
/// lifetime. When working with future and async I/O these lifetimes are not
|
||||
/// always appropriate, and are sometimes difficult to store in tasks. This
|
||||
/// type strives to fill this gap by providing an "owned slice" around an
|
||||
/// underlying buffer of bytes.
|
||||
///
|
||||
/// A `Window<T>` wraps an underlying buffer, `T`, and has configurable
|
||||
/// start/end indexes to alter the behavior of the `AsRef<[u8]>` implementation
|
||||
/// that this type carries.
|
||||
///
|
||||
/// This type can be particularly useful when working with the `write_all`
|
||||
/// combinator in this crate. Data can be sliced via `Window`, consumed by
|
||||
/// `write_all`, and then earned back once the write operation finishes through
|
||||
/// the `into_inner` method on this type.
|
||||
#[derive(Debug)]
|
||||
pub struct Window<T> {
|
||||
inner: T,
|
||||
range: Range<usize>,
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Window<T> {
|
||||
/// Creates a new window around the buffer `t` defaulting to the entire
|
||||
/// slice.
|
||||
///
|
||||
/// Further methods can be called on the returned `Window<T>` to alter the
|
||||
/// window into the data provided.
|
||||
pub fn new(t: T) -> Self {
|
||||
Self { range: 0..t.as_ref().len(), inner: t }
|
||||
}
|
||||
|
||||
/// Gets a shared reference to the underlying buffer inside of this
|
||||
/// `Window`.
|
||||
pub fn get_ref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying buffer inside of this
|
||||
/// `Window`.
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
/// Consumes this `Window`, returning the underlying buffer.
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner
|
||||
}
|
||||
|
||||
/// Returns the starting index of this window into the underlying buffer
|
||||
/// `T`.
|
||||
pub fn start(&self) -> usize {
|
||||
self.range.start
|
||||
}
|
||||
|
||||
/// Returns the end index of this window into the underlying buffer
|
||||
/// `T`.
|
||||
pub fn end(&self) -> usize {
|
||||
self.range.end
|
||||
}
|
||||
|
||||
/// Changes the range of this window to the range specified.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This method will panic if `range` is out of bounds for the underlying
|
||||
/// slice or if [`start_bound()`] of `range` comes after the [`end_bound()`].
|
||||
///
|
||||
/// [`start_bound()`]: std::ops::RangeBounds::start_bound
|
||||
/// [`end_bound()`]: std::ops::RangeBounds::end_bound
|
||||
pub fn set<R: RangeBounds<usize>>(&mut self, range: R) {
|
||||
let start = match range.start_bound() {
|
||||
Bound::Included(n) => *n,
|
||||
Bound::Excluded(n) => *n + 1,
|
||||
Bound::Unbounded => 0,
|
||||
};
|
||||
let end = match range.end_bound() {
|
||||
Bound::Included(n) => *n + 1,
|
||||
Bound::Excluded(n) => *n,
|
||||
Bound::Unbounded => self.inner.as_ref().len(),
|
||||
};
|
||||
|
||||
assert!(end <= self.inner.as_ref().len());
|
||||
assert!(start <= end);
|
||||
|
||||
self.range.start = start;
|
||||
self.range.end = end;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> AsRef<[u8]> for Window<T> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.inner.as_ref()[self.range.start..self.range.end]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsMut<[u8]>> AsMut<[u8]> for Window<T> {
|
||||
fn as_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.inner.as_mut()[self.range.start..self.range.end]
|
||||
}
|
||||
}
|
||||
30
zeroidc/vendor/futures-util/src/io/write.rs
vendored
Normal file
30
zeroidc/vendor/futures-util/src/io/write.rs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
use crate::io::AsyncWrite;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`write`](super::AsyncWriteExt::write) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Write<'a, W: ?Sized> {
|
||||
writer: &'a mut W,
|
||||
buf: &'a [u8],
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Unpin> Unpin for Write<'_, W> {}
|
||||
|
||||
impl<'a, W: AsyncWrite + ?Sized + Unpin> Write<'a, W> {
|
||||
pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self {
|
||||
Self { writer, buf }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + ?Sized + Unpin> Future for Write<'_, W> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
Pin::new(&mut this.writer).poll_write(cx, this.buf)
|
||||
}
|
||||
}
|
||||
43
zeroidc/vendor/futures-util/src/io/write_all.rs
vendored
Normal file
43
zeroidc/vendor/futures-util/src/io/write_all.rs
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncWrite;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`write_all`](super::AsyncWriteExt::write_all) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct WriteAll<'a, W: ?Sized> {
|
||||
writer: &'a mut W,
|
||||
buf: &'a [u8],
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Unpin> Unpin for WriteAll<'_, W> {}
|
||||
|
||||
impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAll<'a, W> {
|
||||
pub(super) fn new(writer: &'a mut W, buf: &'a [u8]) -> Self {
|
||||
Self { writer, buf }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteAll<'_, W> {
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
let this = &mut *self;
|
||||
while !this.buf.is_empty() {
|
||||
let n = ready!(Pin::new(&mut this.writer).poll_write(cx, this.buf))?;
|
||||
{
|
||||
let (_, rest) = mem::replace(&mut this.buf, &[]).split_at(n);
|
||||
this.buf = rest;
|
||||
}
|
||||
if n == 0 {
|
||||
return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
|
||||
}
|
||||
}
|
||||
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
193
zeroidc/vendor/futures-util/src/io/write_all_vectored.rs
vendored
Normal file
193
zeroidc/vendor/futures-util/src/io/write_all_vectored.rs
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_io::AsyncWrite;
|
||||
use futures_io::IoSlice;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the
|
||||
/// [`write_all_vectored`](super::AsyncWriteExt::write_all_vectored) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct WriteAllVectored<'a, W: ?Sized + Unpin> {
|
||||
writer: &'a mut W,
|
||||
bufs: &'a mut [IoSlice<'a>],
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Unpin> Unpin for WriteAllVectored<'_, W> {}
|
||||
|
||||
impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteAllVectored<'a, W> {
|
||||
pub(super) fn new(writer: &'a mut W, mut bufs: &'a mut [IoSlice<'a>]) -> Self {
|
||||
IoSlice::advance_slices(&mut bufs, 0);
|
||||
Self { writer, bufs }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteAllVectored<'_, W> {
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
let this = &mut *self;
|
||||
while !this.bufs.is_empty() {
|
||||
let n = ready!(Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs))?;
|
||||
if n == 0 {
|
||||
return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
|
||||
} else {
|
||||
IoSlice::advance_slices(&mut this.bufs, n);
|
||||
}
|
||||
}
|
||||
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::cmp::min;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use crate::io::{AsyncWrite, AsyncWriteExt, IoSlice};
|
||||
use crate::task::noop_waker;
|
||||
|
||||
/// Create a new writer that reads from at most `n_bufs` and reads
|
||||
/// `per_call` bytes (in total) per call to write.
|
||||
fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
|
||||
TestWriter { n_bufs, per_call, written: Vec::new() }
|
||||
}
|
||||
|
||||
// TODO: maybe move this the future-test crate?
|
||||
struct TestWriter {
|
||||
n_bufs: usize,
|
||||
per_call: usize,
|
||||
written: Vec<u8>,
|
||||
}
|
||||
|
||||
impl AsyncWrite for TestWriter {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
self.poll_write_vectored(cx, &[IoSlice::new(buf)])
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
_cx: &mut Context<'_>,
|
||||
bufs: &[IoSlice<'_>],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
let mut left = self.per_call;
|
||||
let mut written = 0;
|
||||
for buf in bufs.iter().take(self.n_bufs) {
|
||||
let n = min(left, buf.len());
|
||||
self.written.extend_from_slice(&buf[0..n]);
|
||||
left -= n;
|
||||
written += n;
|
||||
}
|
||||
Poll::Ready(Ok(written))
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: maybe move this the future-test crate?
|
||||
macro_rules! assert_poll_ok {
|
||||
($e:expr, $expected:expr) => {
|
||||
let expected = $expected;
|
||||
match $e {
|
||||
Poll::Ready(Ok(ok)) if ok == expected => {}
|
||||
got => {
|
||||
panic!("unexpected result, got: {:?}, wanted: Ready(Ok({:?}))", got, expected)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_writer_read_from_one_buf() {
|
||||
let waker = noop_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
let mut dst = test_writer(1, 2);
|
||||
let mut dst = Pin::new(&mut dst);
|
||||
|
||||
assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[]), 0);
|
||||
assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, &[]), 0);
|
||||
|
||||
// Read at most 2 bytes.
|
||||
assert_poll_ok!(dst.as_mut().poll_write(&mut cx, &[1, 1, 1]), 2);
|
||||
let bufs = &[IoSlice::new(&[2, 2, 2])];
|
||||
assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 2);
|
||||
|
||||
// Only read from first buf.
|
||||
let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])];
|
||||
assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 1);
|
||||
|
||||
assert_eq!(dst.written, &[1, 1, 2, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_writer_read_from_multiple_bufs() {
|
||||
let waker = noop_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
let mut dst = test_writer(3, 3);
|
||||
let mut dst = Pin::new(&mut dst);
|
||||
|
||||
// Read at most 3 bytes from two buffers.
|
||||
let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])];
|
||||
assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3);
|
||||
|
||||
// Read at most 3 bytes from three buffers.
|
||||
let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])];
|
||||
assert_poll_ok!(dst.as_mut().poll_write_vectored(&mut cx, bufs), 3);
|
||||
|
||||
assert_eq!(dst.written, &[1, 2, 2, 3, 4, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_all_vectored() {
|
||||
let waker = noop_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
#[rustfmt::skip] // Becomes unreadable otherwise.
|
||||
let tests: Vec<(_, &'static [u8])> = vec![
|
||||
(vec![], &[]),
|
||||
(vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]),
|
||||
(vec![IoSlice::new(&[1])], &[1]),
|
||||
(vec![IoSlice::new(&[1, 2])], &[1, 2]),
|
||||
(vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]),
|
||||
(vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]),
|
||||
(vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]),
|
||||
(vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]),
|
||||
(vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]),
|
||||
(vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]),
|
||||
(vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]),
|
||||
(vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]),
|
||||
(vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]),
|
||||
(vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]),
|
||||
];
|
||||
|
||||
for (mut input, wanted) in tests {
|
||||
let mut dst = test_writer(2, 2);
|
||||
{
|
||||
let mut future = dst.write_all_vectored(&mut *input);
|
||||
match Pin::new(&mut future).poll(&mut cx) {
|
||||
Poll::Ready(Ok(())) => {}
|
||||
other => panic!("unexpected result polling future: {:?}", other),
|
||||
}
|
||||
}
|
||||
assert_eq!(&*dst.written, &*wanted);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
zeroidc/vendor/futures-util/src/io/write_vectored.rs
vendored
Normal file
30
zeroidc/vendor/futures-util/src/io/write_vectored.rs
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
use crate::io::AsyncWrite;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use std::io::{self, IoSlice};
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Future for the [`write_vectored`](super::AsyncWriteExt::write_vectored) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct WriteVectored<'a, W: ?Sized> {
|
||||
writer: &'a mut W,
|
||||
bufs: &'a [IoSlice<'a>],
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Unpin> Unpin for WriteVectored<'_, W> {}
|
||||
|
||||
impl<'a, W: AsyncWrite + ?Sized + Unpin> WriteVectored<'a, W> {
|
||||
pub(super) fn new(writer: &'a mut W, bufs: &'a [IoSlice<'a>]) -> Self {
|
||||
Self { writer, bufs }
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: AsyncWrite + ?Sized + Unpin> Future for WriteVectored<'_, W> {
|
||||
type Output = io::Result<usize>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
Pin::new(&mut this.writer).poll_write_vectored(cx, this.bufs)
|
||||
}
|
||||
}
|
||||
337
zeroidc/vendor/futures-util/src/lib.rs
vendored
Normal file
337
zeroidc/vendor/futures-util/src/lib.rs
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
//! Combinators and utilities for working with `Future`s, `Stream`s, `Sink`s,
|
||||
//! and the `AsyncRead` and `AsyncWrite` traits.
|
||||
|
||||
#![cfg_attr(feature = "write-all-vectored", feature(io_slice_advance))]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![warn(
|
||||
missing_debug_implementations,
|
||||
missing_docs,
|
||||
rust_2018_idioms,
|
||||
single_use_lifetimes,
|
||||
unreachable_pub
|
||||
)]
|
||||
#![doc(test(
|
||||
no_crate_inject,
|
||||
attr(
|
||||
deny(warnings, rust_2018_idioms, single_use_lifetimes),
|
||||
allow(dead_code, unused_assignments, unused_variables)
|
||||
)
|
||||
))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
#[cfg(all(feature = "bilock", not(feature = "unstable")))]
|
||||
compile_error!("The `bilock` feature requires the `unstable` feature as an explicit opt-in to unstable features");
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
// Macro re-exports
|
||||
pub use futures_core::ready;
|
||||
pub use pin_utils::pin_mut;
|
||||
|
||||
#[cfg(feature = "async-await")]
|
||||
#[macro_use]
|
||||
mod async_await;
|
||||
#[cfg(feature = "async-await")]
|
||||
#[doc(hidden)]
|
||||
pub use self::async_await::*;
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "async-await")]
|
||||
#[doc(hidden)]
|
||||
pub mod __private {
|
||||
pub use crate::*;
|
||||
pub use core::{
|
||||
option::Option::{self, None, Some},
|
||||
pin::Pin,
|
||||
result::Result::{Err, Ok},
|
||||
};
|
||||
|
||||
pub mod async_await {
|
||||
pub use crate::async_await::*;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
macro_rules! delegate_sink {
|
||||
($field:ident, $item:ty) => {
|
||||
fn poll_ready(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Result<(), Self::Error>> {
|
||||
self.project().$field.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn start_send(self: core::pin::Pin<&mut Self>, item: $item) -> Result<(), Self::Error> {
|
||||
self.project().$field.start_send(item)
|
||||
}
|
||||
|
||||
fn poll_flush(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Result<(), Self::Error>> {
|
||||
self.project().$field.poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_close(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Result<(), Self::Error>> {
|
||||
self.project().$field.poll_close(cx)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! delegate_future {
|
||||
($field:ident) => {
|
||||
fn poll(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Self::Output> {
|
||||
self.project().$field.poll(cx)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! delegate_stream {
|
||||
($field:ident) => {
|
||||
fn poll_next(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<Option<Self::Item>> {
|
||||
self.project().$field.poll_next(cx)
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.$field.size_hint()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "io")]
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! delegate_async_write {
|
||||
($field:ident) => {
|
||||
fn poll_write(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> core::task::Poll<std::io::Result<usize>> {
|
||||
self.project().$field.poll_write(cx, buf)
|
||||
}
|
||||
fn poll_write_vectored(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
bufs: &[std::io::IoSlice<'_>],
|
||||
) -> core::task::Poll<std::io::Result<usize>> {
|
||||
self.project().$field.poll_write_vectored(cx, bufs)
|
||||
}
|
||||
fn poll_flush(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<std::io::Result<()>> {
|
||||
self.project().$field.poll_flush(cx)
|
||||
}
|
||||
fn poll_close(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<std::io::Result<()>> {
|
||||
self.project().$field.poll_close(cx)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "io")]
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! delegate_async_read {
|
||||
($field:ident) => {
|
||||
fn poll_read(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> core::task::Poll<std::io::Result<usize>> {
|
||||
self.project().$field.poll_read(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
bufs: &mut [std::io::IoSliceMut<'_>],
|
||||
) -> core::task::Poll<std::io::Result<usize>> {
|
||||
self.project().$field.poll_read_vectored(cx, bufs)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "io")]
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! delegate_async_buf_read {
|
||||
($field:ident) => {
|
||||
fn poll_fill_buf(
|
||||
self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> core::task::Poll<std::io::Result<&[u8]>> {
|
||||
self.project().$field.poll_fill_buf(cx)
|
||||
}
|
||||
|
||||
fn consume(self: core::pin::Pin<&mut Self>, amt: usize) {
|
||||
self.project().$field.consume(amt)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! delegate_access_inner {
|
||||
($field:ident, $inner:ty, ($($ind:tt)*)) => {
|
||||
/// Acquires a reference to the underlying sink or stream that this combinator is
|
||||
/// pulling from.
|
||||
pub fn get_ref(&self) -> &$inner {
|
||||
(&self.$field) $($ind get_ref())*
|
||||
}
|
||||
|
||||
/// Acquires a mutable reference to the underlying sink or stream that this
|
||||
/// combinator is pulling from.
|
||||
///
|
||||
/// Note that care must be taken to avoid tampering with the state of the
|
||||
/// sink or stream which may otherwise confuse this combinator.
|
||||
pub fn get_mut(&mut self) -> &mut $inner {
|
||||
(&mut self.$field) $($ind get_mut())*
|
||||
}
|
||||
|
||||
/// Acquires a pinned mutable reference to the underlying sink or stream that this
|
||||
/// combinator is pulling from.
|
||||
///
|
||||
/// Note that care must be taken to avoid tampering with the state of the
|
||||
/// sink or stream which may otherwise confuse this combinator.
|
||||
pub fn get_pin_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut $inner> {
|
||||
self.project().$field $($ind get_pin_mut())*
|
||||
}
|
||||
|
||||
/// Consumes this combinator, returning the underlying sink or stream.
|
||||
///
|
||||
/// Note that this may discard intermediate state of this combinator, so
|
||||
/// care should be taken to avoid losing resources when this is called.
|
||||
pub fn into_inner(self) -> $inner {
|
||||
self.$field $($ind into_inner())*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! delegate_all {
|
||||
(@trait Future $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> futures_core::future::Future for $name<$($arg),*> where $t: futures_core::future::Future $(, $($bound)*)* {
|
||||
type Output = <$t as futures_core::future::Future>::Output;
|
||||
|
||||
delegate_future!(inner);
|
||||
}
|
||||
};
|
||||
(@trait FusedFuture $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> futures_core::future::FusedFuture for $name<$($arg),*> where $t: futures_core::future::FusedFuture $(, $($bound)*)* {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.inner.is_terminated()
|
||||
}
|
||||
}
|
||||
};
|
||||
(@trait Stream $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> futures_core::stream::Stream for $name<$($arg),*> where $t: futures_core::stream::Stream $(, $($bound)*)* {
|
||||
type Item = <$t as futures_core::stream::Stream>::Item;
|
||||
|
||||
delegate_stream!(inner);
|
||||
}
|
||||
};
|
||||
(@trait FusedStream $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> futures_core::stream::FusedStream for $name<$($arg),*> where $t: futures_core::stream::FusedStream $(, $($bound)*)* {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.inner.is_terminated()
|
||||
}
|
||||
}
|
||||
};
|
||||
(@trait Sink $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
#[cfg(feature = "sink")]
|
||||
impl<_Item, $($arg),*> futures_sink::Sink<_Item> for $name<$($arg),*> where $t: futures_sink::Sink<_Item> $(, $($bound)*)* {
|
||||
type Error = <$t as futures_sink::Sink<_Item>>::Error;
|
||||
|
||||
delegate_sink!(inner, _Item);
|
||||
}
|
||||
};
|
||||
(@trait Debug $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> core::fmt::Debug for $name<$($arg),*> where $t: core::fmt::Debug $(, $($bound)*)* {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
core::fmt::Debug::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
};
|
||||
(@trait AccessInner[$inner:ty, ($($ind:tt)*)] $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> $name<$($arg),*> $(where $($bound)*)* {
|
||||
delegate_access_inner!(inner, $inner, ($($ind)*));
|
||||
}
|
||||
};
|
||||
(@trait New[|$($param:ident: $paramt:ty),*| $cons:expr] $name:ident < $($arg:ident),* > ($t:ty) $(where $($bound:tt)*)*) => {
|
||||
impl<$($arg),*> $name<$($arg),*> $(where $($bound)*)* {
|
||||
pub(crate) fn new($($param: $paramt),*) -> Self {
|
||||
Self { inner: $cons }
|
||||
}
|
||||
}
|
||||
};
|
||||
($(#[$attr:meta])* $name:ident<$($arg:ident),*>($t:ty) : $ftrait:ident $([$($targs:tt)*])* $({$($item:tt)*})* $(where $($bound:tt)*)*) => {
|
||||
pin_project_lite::pin_project! {
|
||||
#[must_use = "futures/streams/sinks do nothing unless you `.await` or poll them"]
|
||||
$(#[$attr])*
|
||||
pub struct $name< $($arg),* > $(where $($bound)*)* { #[pin] inner: $t }
|
||||
}
|
||||
|
||||
impl<$($arg),*> $name< $($arg),* > $(where $($bound)*)* {
|
||||
$($($item)*)*
|
||||
}
|
||||
|
||||
delegate_all!(@trait $ftrait $([$($targs)*])* $name<$($arg),*>($t) $(where $($bound)*)*);
|
||||
};
|
||||
($(#[$attr:meta])* $name:ident<$($arg:ident),*>($t:ty) : $ftrait:ident $([$($ftargs:tt)*])* + $strait:ident $([$($stargs:tt)*])* $(+ $trait:ident $([$($targs:tt)*])*)* $({$($item:tt)*})* $(where $($bound:tt)*)*) => {
|
||||
delegate_all!($(#[$attr])* $name<$($arg),*>($t) : $strait $([$($stargs)*])* $(+ $trait $([$($targs)*])*)* $({$($item)*})* $(where $($bound)*)*);
|
||||
|
||||
delegate_all!(@trait $ftrait $([$($ftargs)*])* $name<$($arg),*>($t) $(where $($bound)*)*);
|
||||
};
|
||||
}
|
||||
|
||||
pub mod future;
|
||||
#[doc(no_inline)]
|
||||
pub use crate::future::{Future, FutureExt, TryFuture, TryFutureExt};
|
||||
|
||||
pub mod stream;
|
||||
#[doc(no_inline)]
|
||||
pub use crate::stream::{Stream, StreamExt, TryStream, TryStreamExt};
|
||||
|
||||
#[cfg(feature = "sink")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "sink")))]
|
||||
pub mod sink;
|
||||
#[cfg(feature = "sink")]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::sink::{Sink, SinkExt};
|
||||
|
||||
pub mod task;
|
||||
|
||||
pub mod never;
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "compat")))]
|
||||
pub mod compat;
|
||||
|
||||
#[cfg(feature = "io")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "io")))]
|
||||
#[cfg(feature = "std")]
|
||||
pub mod io;
|
||||
#[cfg(feature = "io")]
|
||||
#[cfg(feature = "std")]
|
||||
#[doc(no_inline)]
|
||||
pub use crate::io::{
|
||||
AsyncBufRead, AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, AsyncWrite,
|
||||
AsyncWriteExt,
|
||||
};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub mod lock;
|
||||
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
mod abortable;
|
||||
|
||||
mod fns;
|
||||
mod unfold_state;
|
||||
276
zeroidc/vendor/futures-util/src/lock/bilock.rs
vendored
Normal file
276
zeroidc/vendor/futures-util/src/lock/bilock.rs
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
//! Futures-powered synchronization primitives.
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::sync::Arc;
|
||||
use core::cell::UnsafeCell;
|
||||
use core::fmt;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::pin::Pin;
|
||||
use core::sync::atomic::AtomicUsize;
|
||||
use core::sync::atomic::Ordering::SeqCst;
|
||||
#[cfg(feature = "bilock")]
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll, Waker};
|
||||
|
||||
/// A type of futures-powered synchronization primitive which is a mutex between
|
||||
/// two possible owners.
|
||||
///
|
||||
/// This primitive is not as generic as a full-blown mutex but is sufficient for
|
||||
/// many use cases where there are only two possible owners of a resource. The
|
||||
/// implementation of `BiLock` can be more optimized for just the two possible
|
||||
/// owners.
|
||||
///
|
||||
/// Note that it's possible to use this lock through a poll-style interface with
|
||||
/// the `poll_lock` method but you can also use it as a future with the `lock`
|
||||
/// method that consumes a `BiLock` and returns a future that will resolve when
|
||||
/// it's locked.
|
||||
///
|
||||
/// A `BiLock` is typically used for "split" operations where data which serves
|
||||
/// two purposes wants to be split into two to be worked with separately. For
|
||||
/// example a TCP stream could be both a reader and a writer or a framing layer
|
||||
/// could be both a stream and a sink for messages. A `BiLock` enables splitting
|
||||
/// these two and then using each independently in a futures-powered fashion.
|
||||
///
|
||||
/// This type is only available when the `bilock` feature of this
|
||||
/// library is activated.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
pub struct BiLock<T> {
|
||||
arc: Arc<Inner<T>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Inner<T> {
|
||||
state: AtomicUsize,
|
||||
value: Option<UnsafeCell<T>>,
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> Send for Inner<T> {}
|
||||
unsafe impl<T: Send> Sync for Inner<T> {}
|
||||
|
||||
impl<T> BiLock<T> {
|
||||
/// Creates a new `BiLock` protecting the provided data.
|
||||
///
|
||||
/// Two handles to the lock are returned, and these are the only two handles
|
||||
/// that will ever be available to the lock. These can then be sent to separate
|
||||
/// tasks to be managed there.
|
||||
///
|
||||
/// The data behind the bilock is considered to be pinned, which allows `Pin`
|
||||
/// references to locked data. However, this means that the locked value
|
||||
/// will only be available through `Pin<&mut T>` (not `&mut T`) unless `T` is `Unpin`.
|
||||
/// Similarly, reuniting the lock and extracting the inner value is only
|
||||
/// possible when `T` is `Unpin`.
|
||||
pub fn new(t: T) -> (Self, Self) {
|
||||
let arc = Arc::new(Inner { state: AtomicUsize::new(0), value: Some(UnsafeCell::new(t)) });
|
||||
|
||||
(Self { arc: arc.clone() }, Self { arc })
|
||||
}
|
||||
|
||||
/// Attempt to acquire this lock, returning `Pending` if it can't be
|
||||
/// acquired.
|
||||
///
|
||||
/// This function will acquire the lock in a nonblocking fashion, returning
|
||||
/// immediately if the lock is already held. If the lock is successfully
|
||||
/// acquired then `Poll::Ready` is returned with a value that represents
|
||||
/// the locked value (and can be used to access the protected data). The
|
||||
/// lock is unlocked when the returned `BiLockGuard` is dropped.
|
||||
///
|
||||
/// If the lock is already held then this function will return
|
||||
/// `Poll::Pending`. In this case the current task will also be scheduled
|
||||
/// to receive a notification when the lock would otherwise become
|
||||
/// available.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if called outside the context of a future's
|
||||
/// task.
|
||||
pub fn poll_lock(&self, cx: &mut Context<'_>) -> Poll<BiLockGuard<'_, T>> {
|
||||
let mut waker = None;
|
||||
loop {
|
||||
match self.arc.state.swap(1, SeqCst) {
|
||||
// Woohoo, we grabbed the lock!
|
||||
0 => return Poll::Ready(BiLockGuard { bilock: self }),
|
||||
|
||||
// Oops, someone else has locked the lock
|
||||
1 => {}
|
||||
|
||||
// A task was previously blocked on this lock, likely our task,
|
||||
// so we need to update that task.
|
||||
n => unsafe {
|
||||
let mut prev = Box::from_raw(n as *mut Waker);
|
||||
*prev = cx.waker().clone();
|
||||
waker = Some(prev);
|
||||
},
|
||||
}
|
||||
|
||||
// type ascription for safety's sake!
|
||||
let me: Box<Waker> = waker.take().unwrap_or_else(|| Box::new(cx.waker().clone()));
|
||||
let me = Box::into_raw(me) as usize;
|
||||
|
||||
match self.arc.state.compare_exchange(1, me, SeqCst, SeqCst) {
|
||||
// The lock is still locked, but we've now parked ourselves, so
|
||||
// just report that we're scheduled to receive a notification.
|
||||
Ok(_) => return Poll::Pending,
|
||||
|
||||
// Oops, looks like the lock was unlocked after our swap above
|
||||
// and before the compare_exchange. Deallocate what we just
|
||||
// allocated and go through the loop again.
|
||||
Err(0) => unsafe {
|
||||
waker = Some(Box::from_raw(me as *mut Waker));
|
||||
},
|
||||
|
||||
// The top of this loop set the previous state to 1, so if we
|
||||
// failed the CAS above then it's because the previous value was
|
||||
// *not* zero or one. This indicates that a task was blocked,
|
||||
// but we're trying to acquire the lock and there's only one
|
||||
// other reference of the lock, so it should be impossible for
|
||||
// that task to ever block itself.
|
||||
Err(n) => panic!("invalid state: {}", n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a "blocking lock" of this lock, consuming this lock handle and
|
||||
/// returning a future to the acquired lock.
|
||||
///
|
||||
/// This function consumes the `BiLock<T>` and returns a sentinel future,
|
||||
/// `BiLockAcquire<T>`. The returned future will resolve to
|
||||
/// `BiLockAcquired<T>` which represents a locked lock similarly to
|
||||
/// `BiLockGuard<T>`.
|
||||
///
|
||||
/// Note that the returned future will never resolve to an error.
|
||||
#[cfg(feature = "bilock")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
pub fn lock(&self) -> BiLockAcquire<'_, T> {
|
||||
BiLockAcquire { bilock: self }
|
||||
}
|
||||
|
||||
/// Attempts to put the two "halves" of a `BiLock<T>` back together and
|
||||
/// recover the original value. Succeeds only if the two `BiLock<T>`s
|
||||
/// originated from the same call to `BiLock::new`.
|
||||
pub fn reunite(self, other: Self) -> Result<T, ReuniteError<T>>
|
||||
where
|
||||
T: Unpin,
|
||||
{
|
||||
if Arc::ptr_eq(&self.arc, &other.arc) {
|
||||
drop(other);
|
||||
let inner = Arc::try_unwrap(self.arc)
|
||||
.ok()
|
||||
.expect("futures: try_unwrap failed in BiLock<T>::reunite");
|
||||
Ok(unsafe { inner.into_value() })
|
||||
} else {
|
||||
Err(ReuniteError(self, other))
|
||||
}
|
||||
}
|
||||
|
||||
fn unlock(&self) {
|
||||
match self.arc.state.swap(0, SeqCst) {
|
||||
// we've locked the lock, shouldn't be possible for us to see an
|
||||
// unlocked lock.
|
||||
0 => panic!("invalid unlocked state"),
|
||||
|
||||
// Ok, no one else tried to get the lock, we're done.
|
||||
1 => {}
|
||||
|
||||
// Another task has parked themselves on this lock, let's wake them
|
||||
// up as its now their turn.
|
||||
n => unsafe {
|
||||
Box::from_raw(n as *mut Waker).wake();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unpin> Inner<T> {
|
||||
unsafe fn into_value(mut self) -> T {
|
||||
self.value.take().unwrap().into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Inner<T> {
|
||||
fn drop(&mut self) {
|
||||
assert_eq!(self.state.load(SeqCst), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Error indicating two `BiLock<T>`s were not two halves of a whole, and
|
||||
/// thus could not be `reunite`d.
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
pub struct ReuniteError<T>(pub BiLock<T>, pub BiLock<T>);
|
||||
|
||||
impl<T> fmt::Debug for ReuniteError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("ReuniteError").field(&"...").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Display for ReuniteError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "tried to reunite two BiLocks that don't form a pair")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: core::any::Any> std::error::Error for ReuniteError<T> {}
|
||||
|
||||
/// Returned RAII guard from the `poll_lock` method.
|
||||
///
|
||||
/// This structure acts as a sentinel to the data in the `BiLock<T>` itself,
|
||||
/// implementing `Deref` and `DerefMut` to `T`. When dropped, the lock will be
|
||||
/// unlocked.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
pub struct BiLockGuard<'a, T> {
|
||||
bilock: &'a BiLock<T>,
|
||||
}
|
||||
|
||||
impl<T> Deref for BiLockGuard<'_, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.bilock.arc.value.as_ref().unwrap().get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Unpin> DerefMut for BiLockGuard<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.bilock.arc.value.as_ref().unwrap().get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BiLockGuard<'_, T> {
|
||||
/// Get a mutable pinned reference to the locked value.
|
||||
pub fn as_pin_mut(&mut self) -> Pin<&mut T> {
|
||||
// Safety: we never allow moving a !Unpin value out of a bilock, nor
|
||||
// allow mutable access to it
|
||||
unsafe { Pin::new_unchecked(&mut *self.bilock.arc.value.as_ref().unwrap().get()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for BiLockGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
self.bilock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/// Future returned by `BiLock::lock` which will resolve when the lock is
|
||||
/// acquired.
|
||||
#[cfg(feature = "bilock")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct BiLockAcquire<'a, T> {
|
||||
bilock: &'a BiLock<T>,
|
||||
}
|
||||
|
||||
// Pinning is never projected to fields
|
||||
#[cfg(feature = "bilock")]
|
||||
impl<T> Unpin for BiLockAcquire<'_, T> {}
|
||||
|
||||
#[cfg(feature = "bilock")]
|
||||
impl<'a, T> Future for BiLockAcquire<'a, T> {
|
||||
type Output = BiLockGuard<'a, T>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.bilock.poll_lock(cx)
|
||||
}
|
||||
}
|
||||
25
zeroidc/vendor/futures-util/src/lock/mod.rs
vendored
Normal file
25
zeroidc/vendor/futures-util/src/lock/mod.rs
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
//! Futures-powered synchronization primitives.
|
||||
//!
|
||||
//! This module is only available when the `std` or `alloc` feature of this
|
||||
//! library is activated, and it is activated by default.
|
||||
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
#[cfg(feature = "std")]
|
||||
mod mutex;
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
#[cfg(feature = "std")]
|
||||
pub use self::mutex::{MappedMutexGuard, Mutex, MutexGuard, MutexLockFuture};
|
||||
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
#[cfg(any(feature = "bilock", feature = "sink", feature = "io"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
#[cfg_attr(not(feature = "bilock"), allow(unreachable_pub))]
|
||||
mod bilock;
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
#[cfg(any(feature = "sink", feature = "io"))]
|
||||
#[cfg(not(feature = "bilock"))]
|
||||
pub(crate) use self::bilock::BiLock;
|
||||
#[cfg(not(futures_no_atomic_cas))]
|
||||
#[cfg(feature = "bilock")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "bilock")))]
|
||||
pub use self::bilock::{BiLock, BiLockAcquire, BiLockGuard, ReuniteError};
|
||||
406
zeroidc/vendor/futures-util/src/lock/mutex.rs
vendored
Normal file
406
zeroidc/vendor/futures-util/src/lock/mutex.rs
vendored
Normal file
@@ -0,0 +1,406 @@
|
||||
use futures_core::future::{FusedFuture, Future};
|
||||
use futures_core::task::{Context, Poll, Waker};
|
||||
use slab::Slab;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Mutex as StdMutex;
|
||||
use std::{fmt, mem};
|
||||
|
||||
/// A futures-aware mutex.
|
||||
///
|
||||
/// # Fairness
|
||||
///
|
||||
/// This mutex provides no fairness guarantees. Tasks may not acquire the mutex
|
||||
/// in the order that they requested the lock, and it's possible for a single task
|
||||
/// which repeatedly takes the lock to starve other tasks, which may be left waiting
|
||||
/// indefinitely.
|
||||
pub struct Mutex<T: ?Sized> {
|
||||
state: AtomicUsize,
|
||||
waiters: StdMutex<Slab<Waiter>>,
|
||||
value: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> fmt::Debug for Mutex<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let state = self.state.load(Ordering::SeqCst);
|
||||
f.debug_struct("Mutex")
|
||||
.field("is_locked", &((state & IS_LOCKED) != 0))
|
||||
.field("has_waiters", &((state & HAS_WAITERS) != 0))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Mutex<T> {
|
||||
fn from(t: T) -> Self {
|
||||
Self::new(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for Mutex<T> {
|
||||
fn default() -> Self {
|
||||
Self::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
enum Waiter {
|
||||
Waiting(Waker),
|
||||
Woken,
|
||||
}
|
||||
|
||||
impl Waiter {
|
||||
fn register(&mut self, waker: &Waker) {
|
||||
match self {
|
||||
Self::Waiting(w) if waker.will_wake(w) => {}
|
||||
_ => *self = Self::Waiting(waker.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn wake(&mut self) {
|
||||
match mem::replace(self, Self::Woken) {
|
||||
Self::Waiting(waker) => waker.wake(),
|
||||
Self::Woken => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const IS_LOCKED: usize = 1 << 0;
|
||||
const HAS_WAITERS: usize = 1 << 1;
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
/// Creates a new futures-aware mutex.
|
||||
pub fn new(t: T) -> Self {
|
||||
Self {
|
||||
state: AtomicUsize::new(0),
|
||||
waiters: StdMutex::new(Slab::new()),
|
||||
value: UnsafeCell::new(t),
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes this mutex, returning the underlying data.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use futures::lock::Mutex;
|
||||
///
|
||||
/// let mutex = Mutex::new(0);
|
||||
/// assert_eq!(mutex.into_inner(), 0);
|
||||
/// ```
|
||||
pub fn into_inner(self) -> T {
|
||||
self.value.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Mutex<T> {
|
||||
/// Attempt to acquire the lock immediately.
|
||||
///
|
||||
/// If the lock is currently held, this will return `None`.
|
||||
pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
|
||||
let old_state = self.state.fetch_or(IS_LOCKED, Ordering::Acquire);
|
||||
if (old_state & IS_LOCKED) == 0 {
|
||||
Some(MutexGuard { mutex: self })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Acquire the lock asynchronously.
|
||||
///
|
||||
/// This method returns a future that will resolve once the lock has been
|
||||
/// successfully acquired.
|
||||
pub fn lock(&self) -> MutexLockFuture<'_, T> {
|
||||
MutexLockFuture { mutex: Some(self), wait_key: WAIT_KEY_NONE }
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the underlying data.
|
||||
///
|
||||
/// Since this call borrows the `Mutex` mutably, no actual locking needs to
|
||||
/// take place -- the mutable borrow statically guarantees no locks exist.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::lock::Mutex;
|
||||
///
|
||||
/// let mut mutex = Mutex::new(0);
|
||||
/// *mutex.get_mut() = 10;
|
||||
/// assert_eq!(*mutex.lock().await, 10);
|
||||
/// # });
|
||||
/// ```
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
// We know statically that there are no other references to `self`, so
|
||||
// there's no need to lock the inner mutex.
|
||||
unsafe { &mut *self.value.get() }
|
||||
}
|
||||
|
||||
fn remove_waker(&self, wait_key: usize, wake_another: bool) {
|
||||
if wait_key != WAIT_KEY_NONE {
|
||||
let mut waiters = self.waiters.lock().unwrap();
|
||||
match waiters.remove(wait_key) {
|
||||
Waiter::Waiting(_) => {}
|
||||
Waiter::Woken => {
|
||||
// We were awoken, but then dropped before we could
|
||||
// wake up to acquire the lock. Wake up another
|
||||
// waiter.
|
||||
if wake_another {
|
||||
if let Some((_i, waiter)) = waiters.iter_mut().next() {
|
||||
waiter.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if waiters.is_empty() {
|
||||
self.state.fetch_and(!HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unlocks the mutex. Called by MutexGuard and MappedMutexGuard when they are
|
||||
// dropped.
|
||||
fn unlock(&self) {
|
||||
let old_state = self.state.fetch_and(!IS_LOCKED, Ordering::AcqRel);
|
||||
if (old_state & HAS_WAITERS) != 0 {
|
||||
let mut waiters = self.waiters.lock().unwrap();
|
||||
if let Some((_i, waiter)) = waiters.iter_mut().next() {
|
||||
waiter.wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sentinel for when no slot in the `Slab` has been dedicated to this object.
|
||||
const WAIT_KEY_NONE: usize = usize::max_value();
|
||||
|
||||
/// A future which resolves when the target mutex has been successfully acquired.
|
||||
pub struct MutexLockFuture<'a, T: ?Sized> {
|
||||
// `None` indicates that the mutex was successfully acquired.
|
||||
mutex: Option<&'a Mutex<T>>,
|
||||
wait_key: usize,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> fmt::Debug for MutexLockFuture<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("MutexLockFuture")
|
||||
.field("was_acquired", &self.mutex.is_none())
|
||||
.field("mutex", &self.mutex)
|
||||
.field(
|
||||
"wait_key",
|
||||
&(if self.wait_key == WAIT_KEY_NONE { None } else { Some(self.wait_key) }),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> FusedFuture for MutexLockFuture<'_, T> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.mutex.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Future for MutexLockFuture<'a, T> {
|
||||
type Output = MutexGuard<'a, T>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mutex = self.mutex.expect("polled MutexLockFuture after completion");
|
||||
|
||||
if let Some(lock) = mutex.try_lock() {
|
||||
mutex.remove_waker(self.wait_key, false);
|
||||
self.mutex = None;
|
||||
return Poll::Ready(lock);
|
||||
}
|
||||
|
||||
{
|
||||
let mut waiters = mutex.waiters.lock().unwrap();
|
||||
if self.wait_key == WAIT_KEY_NONE {
|
||||
self.wait_key = waiters.insert(Waiter::Waiting(cx.waker().clone()));
|
||||
if waiters.len() == 1 {
|
||||
mutex.state.fetch_or(HAS_WAITERS, Ordering::Relaxed); // released by mutex unlock
|
||||
}
|
||||
} else {
|
||||
waiters[self.wait_key].register(cx.waker());
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that we haven't raced `MutexGuard::drop`'s unlock path by
|
||||
// attempting to acquire the lock again.
|
||||
if let Some(lock) = mutex.try_lock() {
|
||||
mutex.remove_waker(self.wait_key, false);
|
||||
self.mutex = None;
|
||||
return Poll::Ready(lock);
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for MutexLockFuture<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(mutex) = self.mutex {
|
||||
// This future was dropped before it acquired the mutex.
|
||||
//
|
||||
// Remove ourselves from the map, waking up another waiter if we
|
||||
// had been awoken to acquire the lock.
|
||||
mutex.remove_waker(self.wait_key, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An RAII guard returned by the `lock` and `try_lock` methods.
|
||||
/// When this structure is dropped (falls out of scope), the lock will be
|
||||
/// unlocked.
|
||||
pub struct MutexGuard<'a, T: ?Sized> {
|
||||
mutex: &'a Mutex<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> MutexGuard<'a, T> {
|
||||
/// Returns a locked view over a portion of the locked data.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::lock::{Mutex, MutexGuard};
|
||||
///
|
||||
/// let data = Mutex::new(Some("value".to_string()));
|
||||
/// {
|
||||
/// let locked_str = MutexGuard::map(data.lock().await, |opt| opt.as_mut().unwrap());
|
||||
/// assert_eq!(&*locked_str, "value");
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn map<U: ?Sized, F>(this: Self, f: F) -> MappedMutexGuard<'a, T, U>
|
||||
where
|
||||
F: FnOnce(&mut T) -> &mut U,
|
||||
{
|
||||
let mutex = this.mutex;
|
||||
let value = f(unsafe { &mut *this.mutex.value.get() });
|
||||
// Don't run the `drop` method for MutexGuard. The ownership of the underlying
|
||||
// locked state is being moved to the returned MappedMutexGuard.
|
||||
mem::forget(this);
|
||||
MappedMutexGuard { mutex, value, _marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("MutexGuard").field("value", &&**self).field("mutex", &self.mutex).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for MutexGuard<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
self.mutex.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Deref for MutexGuard<'_, T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.mutex.value.get() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.mutex.value.get() }
|
||||
}
|
||||
}
|
||||
|
||||
/// An RAII guard returned by the `MutexGuard::map` and `MappedMutexGuard::map` methods.
|
||||
/// When this structure is dropped (falls out of scope), the lock will be unlocked.
|
||||
pub struct MappedMutexGuard<'a, T: ?Sized, U: ?Sized> {
|
||||
mutex: &'a Mutex<T>,
|
||||
value: *mut U,
|
||||
_marker: PhantomData<&'a mut U>,
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized, U: ?Sized> MappedMutexGuard<'a, T, U> {
|
||||
/// Returns a locked view over a portion of the locked data.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::lock::{MappedMutexGuard, Mutex, MutexGuard};
|
||||
///
|
||||
/// let data = Mutex::new(Some("value".to_string()));
|
||||
/// {
|
||||
/// let locked_str = MutexGuard::map(data.lock().await, |opt| opt.as_mut().unwrap());
|
||||
/// let locked_char = MappedMutexGuard::map(locked_str, |s| s.get_mut(0..1).unwrap());
|
||||
/// assert_eq!(&*locked_char, "v");
|
||||
/// }
|
||||
/// # });
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn map<V: ?Sized, F>(this: Self, f: F) -> MappedMutexGuard<'a, T, V>
|
||||
where
|
||||
F: FnOnce(&mut U) -> &mut V,
|
||||
{
|
||||
let mutex = this.mutex;
|
||||
let value = f(unsafe { &mut *this.value });
|
||||
// Don't run the `drop` method for MappedMutexGuard. The ownership of the underlying
|
||||
// locked state is being moved to the returned MappedMutexGuard.
|
||||
mem::forget(this);
|
||||
MappedMutexGuard { mutex, value, _marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'_, T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("MappedMutexGuard")
|
||||
.field("value", &&**self)
|
||||
.field("mutex", &self.mutex)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> Drop for MappedMutexGuard<'_, T, U> {
|
||||
fn drop(&mut self) {
|
||||
self.mutex.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> Deref for MappedMutexGuard<'_, T, U> {
|
||||
type Target = U;
|
||||
fn deref(&self) -> &U {
|
||||
unsafe { &*self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> DerefMut for MappedMutexGuard<'_, T, U> {
|
||||
fn deref_mut(&mut self) -> &mut U {
|
||||
unsafe { &mut *self.value }
|
||||
}
|
||||
}
|
||||
|
||||
// Mutexes can be moved freely between threads and acquired on any thread so long
|
||||
// as the inner value can be safely sent between threads.
|
||||
unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
|
||||
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
|
||||
|
||||
// It's safe to switch which thread the acquire is being attempted on so long as
|
||||
// `T` can be accessed on that thread.
|
||||
unsafe impl<T: ?Sized + Send> Send for MutexLockFuture<'_, T> {}
|
||||
// doesn't have any interesting `&self` methods (only Debug)
|
||||
unsafe impl<T: ?Sized> Sync for MutexLockFuture<'_, T> {}
|
||||
|
||||
// Safe to send since we don't track any thread-specific details-- the inner
|
||||
// lock is essentially spinlock-equivalent (attempt to flip an atomic bool)
|
||||
unsafe impl<T: ?Sized + Send> Send for MutexGuard<'_, T> {}
|
||||
unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {}
|
||||
unsafe impl<T: ?Sized + Send, U: ?Sized + Send> Send for MappedMutexGuard<'_, T, U> {}
|
||||
unsafe impl<T: ?Sized + Sync, U: ?Sized + Sync> Sync for MappedMutexGuard<'_, T, U> {}
|
||||
|
||||
#[test]
|
||||
fn test_mutex_guard_debug_not_recurse() {
|
||||
let mutex = Mutex::new(42);
|
||||
let guard = mutex.try_lock().unwrap();
|
||||
let _ = format!("{:?}", guard);
|
||||
let guard = MutexGuard::map(guard, |n| n);
|
||||
let _ = format!("{:?}", guard);
|
||||
}
|
||||
18
zeroidc/vendor/futures-util/src/never.rs
vendored
Normal file
18
zeroidc/vendor/futures-util/src/never.rs
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
//! This module contains the `Never` type.
|
||||
//!
|
||||
//! Values of this type can never be created and will never exist.
|
||||
|
||||
/// A type with no possible values.
|
||||
///
|
||||
/// This is used to indicate values which can never be created, such as the
|
||||
/// error type of infallible futures.
|
||||
///
|
||||
/// This type is a stable equivalent to the `!` type from `std`.
|
||||
///
|
||||
/// This is currently an alias for [`std::convert::Infallible`], but in
|
||||
/// the future it may be an alias for [`!`][never].
|
||||
/// See ["Future compatibility" section of `std::convert::Infallible`][infallible] for more.
|
||||
///
|
||||
/// [never]: https://doc.rust-lang.org/nightly/std/primitive.never.html
|
||||
/// [infallible]: https://doc.rust-lang.org/nightly/std/convert/enum.Infallible.html#future-compatibility
|
||||
pub type Never = core::convert::Infallible;
|
||||
105
zeroidc/vendor/futures-util/src/sink/buffer.rs
vendored
Normal file
105
zeroidc/vendor/futures-util/src/sink/buffer.rs
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
use alloc::collections::VecDeque;
|
||||
use core::pin::Pin;
|
||||
use futures_core::ready;
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`buffer`](super::SinkExt::buffer) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct Buffer<Si, Item> {
|
||||
#[pin]
|
||||
sink: Si,
|
||||
buf: VecDeque<Item>,
|
||||
|
||||
// Track capacity separately from the `VecDeque`, which may be rounded up
|
||||
capacity: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si: Sink<Item>, Item> Buffer<Si, Item> {
|
||||
pub(super) fn new(sink: Si, capacity: usize) -> Self {
|
||||
Self { sink, buf: VecDeque::with_capacity(capacity), capacity }
|
||||
}
|
||||
|
||||
delegate_access_inner!(sink, Si, ());
|
||||
|
||||
fn try_empty_buffer(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Si::Error>> {
|
||||
let mut this = self.project();
|
||||
ready!(this.sink.as_mut().poll_ready(cx))?;
|
||||
while let Some(item) = this.buf.pop_front() {
|
||||
this.sink.as_mut().start_send(item)?;
|
||||
if !this.buf.is_empty() {
|
||||
ready!(this.sink.as_mut().poll_ready(cx))?;
|
||||
}
|
||||
}
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
// Forwarding impl of Stream from the underlying sink
|
||||
impl<S, Item> Stream for Buffer<S, Item>
|
||||
where
|
||||
S: Sink<Item> + Stream,
|
||||
{
|
||||
type Item = S::Item;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {
|
||||
self.project().sink.poll_next(cx)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.sink.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, Item> FusedStream for Buffer<S, Item>
|
||||
where
|
||||
S: Sink<Item> + FusedStream,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.sink.is_terminated()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si: Sink<Item>, Item> Sink<Item> for Buffer<Si, Item> {
|
||||
type Error = Si::Error;
|
||||
|
||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
if self.capacity == 0 {
|
||||
return self.project().sink.poll_ready(cx);
|
||||
}
|
||||
|
||||
let _ = self.as_mut().try_empty_buffer(cx)?;
|
||||
|
||||
if self.buf.len() >= self.capacity {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
|
||||
if self.capacity == 0 {
|
||||
self.project().sink.start_send(item)
|
||||
} else {
|
||||
self.project().buf.push_back(item);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().try_empty_buffer(cx))?;
|
||||
debug_assert!(self.buf.is_empty());
|
||||
self.project().sink.poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().try_empty_buffer(cx))?;
|
||||
debug_assert!(self.buf.is_empty());
|
||||
self.project().sink.poll_close(cx)
|
||||
}
|
||||
}
|
||||
32
zeroidc/vendor/futures-util/src/sink/close.rs
vendored
Normal file
32
zeroidc/vendor/futures-util/src/sink/close.rs
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
|
||||
/// Future for the [`close`](super::SinkExt::close) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Close<'a, Si: ?Sized, Item> {
|
||||
sink: &'a mut Si,
|
||||
_phantom: PhantomData<fn(Item)>,
|
||||
}
|
||||
|
||||
impl<Si: Unpin + ?Sized, Item> Unpin for Close<'_, Si, Item> {}
|
||||
|
||||
/// A future that completes when the sink has finished closing.
|
||||
///
|
||||
/// The sink itself is returned after closing is complete.
|
||||
impl<'a, Si: Sink<Item> + Unpin + ?Sized, Item> Close<'a, Si, Item> {
|
||||
pub(super) fn new(sink: &'a mut Si) -> Self {
|
||||
Self { sink, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si: Sink<Item> + Unpin + ?Sized, Item> Future for Close<'_, Si, Item> {
|
||||
type Output = Result<(), Si::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::new(&mut self.sink).poll_close(cx)
|
||||
}
|
||||
}
|
||||
53
zeroidc/vendor/futures-util/src/sink/drain.rs
vendored
Normal file
53
zeroidc/vendor/futures-util/src/sink/drain.rs
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
use super::assert_sink;
|
||||
use crate::never::Never;
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
|
||||
/// Sink for the [`drain`] function.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct Drain<T> {
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
/// Create a sink that will just discard all items given to it.
|
||||
///
|
||||
/// Similar to [`io::Sink`](::std::io::Sink).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::sink::{self, SinkExt};
|
||||
///
|
||||
/// let mut drain = sink::drain();
|
||||
/// drain.send(5).await?;
|
||||
/// # Ok::<(), futures::never::Never>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn drain<T>() -> Drain<T> {
|
||||
assert_sink::<T, Never, _>(Drain { marker: PhantomData })
|
||||
}
|
||||
|
||||
impl<T> Unpin for Drain<T> {}
|
||||
|
||||
impl<T> Sink<T> for Drain<T> {
|
||||
type Error = Never;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, _item: T) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
57
zeroidc/vendor/futures-util/src/sink/err_into.rs
vendored
Normal file
57
zeroidc/vendor/futures-util/src/sink/err_into.rs
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
use crate::sink::{SinkExt, SinkMapErr};
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`sink_err_into`](super::SinkExt::sink_err_into) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct SinkErrInto<Si: Sink<Item>, Item, E> {
|
||||
#[pin]
|
||||
sink: SinkMapErr<Si, fn(Si::Error) -> E>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, E, Item> SinkErrInto<Si, Item, E>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
Si::Error: Into<E>,
|
||||
{
|
||||
pub(super) fn new(sink: Si) -> Self {
|
||||
Self { sink: SinkExt::sink_map_err(sink, Into::into) }
|
||||
}
|
||||
|
||||
delegate_access_inner!(sink, Si, (.));
|
||||
}
|
||||
|
||||
impl<Si, Item, E> Sink<Item> for SinkErrInto<Si, Item, E>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
Si::Error: Into<E>,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
delegate_sink!(sink, Item);
|
||||
}
|
||||
|
||||
// Forwarding impl of Stream from the underlying sink
|
||||
impl<S, Item, E> Stream for SinkErrInto<S, Item, E>
|
||||
where
|
||||
S: Sink<Item> + Stream,
|
||||
S::Error: Into<E>,
|
||||
{
|
||||
type Item = S::Item;
|
||||
|
||||
delegate_stream!(sink);
|
||||
}
|
||||
|
||||
impl<S, Item, E> FusedStream for SinkErrInto<S, Item, E>
|
||||
where
|
||||
S: Sink<Item> + FusedStream,
|
||||
S::Error: Into<E>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.sink.is_terminated()
|
||||
}
|
||||
}
|
||||
111
zeroidc/vendor/futures-util/src/sink/fanout.rs
vendored
Normal file
111
zeroidc/vendor/futures-util/src/sink/fanout.rs
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
use core::fmt::{Debug, Formatter, Result as FmtResult};
|
||||
use core::pin::Pin;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink that clones incoming items and forwards them to two sinks at the same time.
|
||||
///
|
||||
/// Backpressure from any downstream sink propagates up, which means that this sink
|
||||
/// can only process items as fast as its _slowest_ downstream sink.
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct Fanout<Si1, Si2> {
|
||||
#[pin]
|
||||
sink1: Si1,
|
||||
#[pin]
|
||||
sink2: Si2
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si1, Si2> Fanout<Si1, Si2> {
|
||||
pub(super) fn new(sink1: Si1, sink2: Si2) -> Self {
|
||||
Self { sink1, sink2 }
|
||||
}
|
||||
|
||||
/// Get a shared reference to the inner sinks.
|
||||
pub fn get_ref(&self) -> (&Si1, &Si2) {
|
||||
(&self.sink1, &self.sink2)
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the inner sinks.
|
||||
pub fn get_mut(&mut self) -> (&mut Si1, &mut Si2) {
|
||||
(&mut self.sink1, &mut self.sink2)
|
||||
}
|
||||
|
||||
/// Get a pinned mutable reference to the inner sinks.
|
||||
pub fn get_pin_mut(self: Pin<&mut Self>) -> (Pin<&mut Si1>, Pin<&mut Si2>) {
|
||||
let this = self.project();
|
||||
(this.sink1, this.sink2)
|
||||
}
|
||||
|
||||
/// Consumes this combinator, returning the underlying sinks.
|
||||
///
|
||||
/// Note that this may discard intermediate state of this combinator,
|
||||
/// so care should be taken to avoid losing resources when this is called.
|
||||
pub fn into_inner(self) -> (Si1, Si2) {
|
||||
(self.sink1, self.sink2)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si1: Debug, Si2: Debug> Debug for Fanout<Si1, Si2> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
f.debug_struct("Fanout").field("sink1", &self.sink1).field("sink2", &self.sink2).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si1, Si2, Item> Sink<Item> for Fanout<Si1, Si2>
|
||||
where
|
||||
Si1: Sink<Item>,
|
||||
Item: Clone,
|
||||
Si2: Sink<Item, Error = Si1::Error>,
|
||||
{
|
||||
type Error = Si1::Error;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let this = self.project();
|
||||
|
||||
let sink1_ready = this.sink1.poll_ready(cx)?.is_ready();
|
||||
let sink2_ready = this.sink2.poll_ready(cx)?.is_ready();
|
||||
let ready = sink1_ready && sink2_ready;
|
||||
if ready {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
|
||||
let this = self.project();
|
||||
|
||||
this.sink1.start_send(item.clone())?;
|
||||
this.sink2.start_send(item)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let this = self.project();
|
||||
|
||||
let sink1_ready = this.sink1.poll_flush(cx)?.is_ready();
|
||||
let sink2_ready = this.sink2.poll_flush(cx)?.is_ready();
|
||||
let ready = sink1_ready && sink2_ready;
|
||||
if ready {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let this = self.project();
|
||||
|
||||
let sink1_ready = this.sink1.poll_close(cx)?.is_ready();
|
||||
let sink2_ready = this.sink2.poll_close(cx)?.is_ready();
|
||||
let ready = sink1_ready && sink2_ready;
|
||||
if ready {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
43
zeroidc/vendor/futures-util/src/sink/feed.rs
vendored
Normal file
43
zeroidc/vendor/futures-util/src/sink/feed.rs
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
|
||||
/// Future for the [`feed`](super::SinkExt::feed) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Feed<'a, Si: ?Sized, Item> {
|
||||
sink: &'a mut Si,
|
||||
item: Option<Item>,
|
||||
}
|
||||
|
||||
// Pinning is never projected to children
|
||||
impl<Si: Unpin + ?Sized, Item> Unpin for Feed<'_, Si, Item> {}
|
||||
|
||||
impl<'a, Si: Sink<Item> + Unpin + ?Sized, Item> Feed<'a, Si, Item> {
|
||||
pub(super) fn new(sink: &'a mut Si, item: Item) -> Self {
|
||||
Feed { sink, item: Some(item) }
|
||||
}
|
||||
|
||||
pub(super) fn sink_pin_mut(&mut self) -> Pin<&mut Si> {
|
||||
Pin::new(self.sink)
|
||||
}
|
||||
|
||||
pub(super) fn is_item_pending(&self) -> bool {
|
||||
self.item.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si: Sink<Item> + Unpin + ?Sized, Item> Future for Feed<'_, Si, Item> {
|
||||
type Output = Result<(), Si::Error>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
let mut sink = Pin::new(&mut this.sink);
|
||||
ready!(sink.as_mut().poll_ready(cx))?;
|
||||
let item = this.item.take().expect("polled Feed after completion");
|
||||
sink.as_mut().start_send(item)?;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
36
zeroidc/vendor/futures-util/src/sink/flush.rs
vendored
Normal file
36
zeroidc/vendor/futures-util/src/sink/flush.rs
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
|
||||
/// Future for the [`flush`](super::SinkExt::flush) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Flush<'a, Si: ?Sized, Item> {
|
||||
sink: &'a mut Si,
|
||||
_phantom: PhantomData<fn(Item)>,
|
||||
}
|
||||
|
||||
// Pin is never projected to a field.
|
||||
impl<Si: Unpin + ?Sized, Item> Unpin for Flush<'_, Si, Item> {}
|
||||
|
||||
/// A future that completes when the sink has finished processing all
|
||||
/// pending requests.
|
||||
///
|
||||
/// The sink itself is returned after flushing is complete; this adapter is
|
||||
/// intended to be used when you want to stop sending to the sink until
|
||||
/// all current requests are processed.
|
||||
impl<'a, Si: Sink<Item> + Unpin + ?Sized, Item> Flush<'a, Si, Item> {
|
||||
pub(super) fn new(sink: &'a mut Si) -> Self {
|
||||
Self { sink, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si: Sink<Item> + Unpin + ?Sized, Item> Future for Flush<'_, Si, Item> {
|
||||
type Output = Result<(), Si::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::new(&mut self.sink).poll_flush(cx)
|
||||
}
|
||||
}
|
||||
65
zeroidc/vendor/futures-util/src/sink/map_err.rs
vendored
Normal file
65
zeroidc/vendor/futures-util/src/sink/map_err.rs
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
use core::pin::Pin;
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`sink_map_err`](super::SinkExt::sink_map_err) method.
|
||||
#[derive(Debug, Clone)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct SinkMapErr<Si, F> {
|
||||
#[pin]
|
||||
sink: Si,
|
||||
f: Option<F>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, F> SinkMapErr<Si, F> {
|
||||
pub(super) fn new(sink: Si, f: F) -> Self {
|
||||
Self { sink, f: Some(f) }
|
||||
}
|
||||
|
||||
delegate_access_inner!(sink, Si, ());
|
||||
|
||||
fn take_f(self: Pin<&mut Self>) -> F {
|
||||
self.project().f.take().expect("polled MapErr after completion")
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, F, E, Item> Sink<Item> for SinkMapErr<Si, F>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
F: FnOnce(Si::Error) -> E,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.as_mut().project().sink.poll_ready(cx).map_err(|e| self.as_mut().take_f()(e))
|
||||
}
|
||||
|
||||
fn start_send(mut self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
|
||||
self.as_mut().project().sink.start_send(item).map_err(|e| self.as_mut().take_f()(e))
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.as_mut().project().sink.poll_flush(cx).map_err(|e| self.as_mut().take_f()(e))
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.as_mut().project().sink.poll_close(cx).map_err(|e| self.as_mut().take_f()(e))
|
||||
}
|
||||
}
|
||||
|
||||
// Forwarding impl of Stream from the underlying sink
|
||||
impl<S: Stream, F> Stream for SinkMapErr<S, F> {
|
||||
type Item = S::Item;
|
||||
|
||||
delegate_stream!(sink);
|
||||
}
|
||||
|
||||
impl<S: FusedStream, F> FusedStream for SinkMapErr<S, F> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.sink.is_terminated()
|
||||
}
|
||||
}
|
||||
344
zeroidc/vendor/futures-util/src/sink/mod.rs
vendored
Normal file
344
zeroidc/vendor/futures-util/src/sink/mod.rs
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
//! Asynchronous sinks.
|
||||
//!
|
||||
//! This module contains:
|
||||
//!
|
||||
//! - The [`Sink`] trait, which allows you to asynchronously write data.
|
||||
//! - The [`SinkExt`] trait, which provides adapters for chaining and composing
|
||||
//! sinks.
|
||||
|
||||
use crate::future::{assert_future, Either};
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::stream::{Stream, TryStream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
|
||||
#[cfg(feature = "compat")]
|
||||
use crate::compat::CompatSink;
|
||||
|
||||
pub use futures_sink::Sink;
|
||||
|
||||
mod close;
|
||||
pub use self::close::Close;
|
||||
|
||||
mod drain;
|
||||
pub use self::drain::{drain, Drain};
|
||||
|
||||
mod fanout;
|
||||
pub use self::fanout::Fanout;
|
||||
|
||||
mod feed;
|
||||
pub use self::feed::Feed;
|
||||
|
||||
mod flush;
|
||||
pub use self::flush::Flush;
|
||||
|
||||
mod err_into;
|
||||
pub use self::err_into::SinkErrInto;
|
||||
|
||||
mod map_err;
|
||||
pub use self::map_err::SinkMapErr;
|
||||
|
||||
mod send;
|
||||
pub use self::send::Send;
|
||||
|
||||
mod send_all;
|
||||
pub use self::send_all::SendAll;
|
||||
|
||||
mod unfold;
|
||||
pub use self::unfold::{unfold, Unfold};
|
||||
|
||||
mod with;
|
||||
pub use self::with::With;
|
||||
|
||||
mod with_flat_map;
|
||||
pub use self::with_flat_map::WithFlatMap;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
mod buffer;
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use self::buffer::Buffer;
|
||||
|
||||
impl<T: ?Sized, Item> SinkExt<Item> for T where T: Sink<Item> {}
|
||||
|
||||
/// An extension trait for `Sink`s that provides a variety of convenient
|
||||
/// combinator functions.
|
||||
pub trait SinkExt<Item>: Sink<Item> {
|
||||
/// Composes a function *in front of* the sink.
|
||||
///
|
||||
/// This adapter produces a new sink that passes each value through the
|
||||
/// given function `f` before sending it to `self`.
|
||||
///
|
||||
/// To process each value, `f` produces a *future*, which is then polled to
|
||||
/// completion before passing its result down to the underlying sink. If the
|
||||
/// future produces an error, that error is returned by the new sink.
|
||||
///
|
||||
/// Note that this function consumes the given sink, returning a wrapped
|
||||
/// version, much like `Iterator::map`.
|
||||
fn with<U, Fut, F, E>(self, f: F) -> With<Self, Item, U, Fut, F>
|
||||
where
|
||||
F: FnMut(U) -> Fut,
|
||||
Fut: Future<Output = Result<Item, E>>,
|
||||
E: From<Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_sink::<U, E, _>(With::new(self, f))
|
||||
}
|
||||
|
||||
/// Composes a function *in front of* the sink.
|
||||
///
|
||||
/// This adapter produces a new sink that passes each value through the
|
||||
/// given function `f` before sending it to `self`.
|
||||
///
|
||||
/// To process each value, `f` produces a *stream*, of which each value
|
||||
/// is passed to the underlying sink. A new value will not be accepted until
|
||||
/// the stream has been drained
|
||||
///
|
||||
/// Note that this function consumes the given sink, returning a wrapped
|
||||
/// version, much like `Iterator::flat_map`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::channel::mpsc;
|
||||
/// use futures::sink::SinkExt;
|
||||
/// use futures::stream::{self, StreamExt};
|
||||
///
|
||||
/// let (tx, rx) = mpsc::channel(5);
|
||||
///
|
||||
/// let mut tx = tx.with_flat_map(|x| {
|
||||
/// stream::iter(vec![Ok(42); x])
|
||||
/// });
|
||||
///
|
||||
/// tx.send(5).await.unwrap();
|
||||
/// drop(tx);
|
||||
/// let received: Vec<i32> = rx.collect().await;
|
||||
/// assert_eq!(received, vec![42, 42, 42, 42, 42]);
|
||||
/// # });
|
||||
/// ```
|
||||
fn with_flat_map<U, St, F>(self, f: F) -> WithFlatMap<Self, Item, U, St, F>
|
||||
where
|
||||
F: FnMut(U) -> St,
|
||||
St: Stream<Item = Result<Item, Self::Error>>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_sink::<U, Self::Error, _>(WithFlatMap::new(self, f))
|
||||
}
|
||||
|
||||
/*
|
||||
fn with_map<U, F>(self, f: F) -> WithMap<Self, U, F>
|
||||
where F: FnMut(U) -> Self::SinkItem,
|
||||
Self: Sized;
|
||||
|
||||
fn with_filter<F>(self, f: F) -> WithFilter<Self, F>
|
||||
where F: FnMut(Self::SinkItem) -> bool,
|
||||
Self: Sized;
|
||||
|
||||
fn with_filter_map<U, F>(self, f: F) -> WithFilterMap<Self, U, F>
|
||||
where F: FnMut(U) -> Option<Self::SinkItem>,
|
||||
Self: Sized;
|
||||
*/
|
||||
|
||||
/// Transforms the error returned by the sink.
|
||||
fn sink_map_err<E, F>(self, f: F) -> SinkMapErr<Self, F>
|
||||
where
|
||||
F: FnOnce(Self::Error) -> E,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_sink::<Item, E, _>(SinkMapErr::new(self, f))
|
||||
}
|
||||
|
||||
/// Map this sink's error to a different error type using the `Into` trait.
|
||||
///
|
||||
/// If wanting to map errors of a `Sink + Stream`, use `.sink_err_into().err_into()`.
|
||||
fn sink_err_into<E>(self) -> err_into::SinkErrInto<Self, Item, E>
|
||||
where
|
||||
Self: Sized,
|
||||
Self::Error: Into<E>,
|
||||
{
|
||||
assert_sink::<Item, E, _>(SinkErrInto::new(self))
|
||||
}
|
||||
|
||||
/// Adds a fixed-size buffer to the current sink.
|
||||
///
|
||||
/// The resulting sink will buffer up to `capacity` items when the
|
||||
/// underlying sink is unwilling to accept additional items. Calling `flush`
|
||||
/// on the buffered sink will attempt to both empty the buffer and complete
|
||||
/// processing on the underlying sink.
|
||||
///
|
||||
/// Note that this function consumes the given sink, returning a wrapped
|
||||
/// version, much like `Iterator::map`.
|
||||
///
|
||||
/// 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 buffer(self, capacity: usize) -> Buffer<Self, Item>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
assert_sink::<Item, Self::Error, _>(Buffer::new(self, capacity))
|
||||
}
|
||||
|
||||
/// Close the sink.
|
||||
fn close(&mut self) -> Close<'_, Self, Item>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<(), Self::Error>, _>(Close::new(self))
|
||||
}
|
||||
|
||||
/// Fanout items to multiple sinks.
|
||||
///
|
||||
/// This adapter clones each incoming item and forwards it to both this as well as
|
||||
/// the other sink at the same time.
|
||||
fn fanout<Si>(self, other: Si) -> Fanout<Self, Si>
|
||||
where
|
||||
Self: Sized,
|
||||
Item: Clone,
|
||||
Si: Sink<Item, Error = Self::Error>,
|
||||
{
|
||||
assert_sink::<Item, Self::Error, _>(Fanout::new(self, other))
|
||||
}
|
||||
|
||||
/// Flush the sink, processing all pending items.
|
||||
///
|
||||
/// This adapter is intended to be used when you want to stop sending to the sink
|
||||
/// until all current requests are processed.
|
||||
fn flush(&mut self) -> Flush<'_, Self, Item>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<(), Self::Error>, _>(Flush::new(self))
|
||||
}
|
||||
|
||||
/// A future that completes after the given item has been fully processed
|
||||
/// into the sink, including flushing.
|
||||
///
|
||||
/// Note that, **because of the flushing requirement, it is usually better
|
||||
/// to batch together items to send via `feed` or `send_all`,
|
||||
/// rather than flushing between each item.**
|
||||
fn send(&mut self, item: Item) -> Send<'_, Self, Item>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<(), Self::Error>, _>(Send::new(self, item))
|
||||
}
|
||||
|
||||
/// A future that completes after the given item has been received
|
||||
/// by the sink.
|
||||
///
|
||||
/// Unlike `send`, the returned future does not flush the sink.
|
||||
/// It is the caller's responsibility to ensure all pending items
|
||||
/// are processed, which can be done via `flush` or `close`.
|
||||
fn feed(&mut self, item: Item) -> Feed<'_, Self, Item>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
assert_future::<Result<(), Self::Error>, _>(Feed::new(self, item))
|
||||
}
|
||||
|
||||
/// A future that completes after the given stream has been fully processed
|
||||
/// into the sink, including flushing.
|
||||
///
|
||||
/// This future will drive the stream to keep producing items until it is
|
||||
/// exhausted, sending each item to the sink. It will complete once both the
|
||||
/// stream is exhausted, the sink has received all items, and the sink has
|
||||
/// been flushed. Note that the sink is **not** closed. If the stream produces
|
||||
/// an error, that error will be returned by this future without flushing the sink.
|
||||
///
|
||||
/// Doing `sink.send_all(stream)` is roughly equivalent to
|
||||
/// `stream.forward(sink)`. The returned future will exhaust all items from
|
||||
/// `stream` and send them to `self`.
|
||||
fn send_all<'a, St>(&'a mut self, stream: &'a mut St) -> SendAll<'a, Self, St>
|
||||
where
|
||||
St: TryStream<Ok = Item, Error = Self::Error> + Stream + Unpin + ?Sized,
|
||||
// St: Stream<Item = Result<Item, Self::Error>> + Unpin + ?Sized,
|
||||
Self: Unpin,
|
||||
{
|
||||
// TODO: type mismatch resolving `<St as Stream>::Item == std::result::Result<Item, <Self as futures_sink::Sink<Item>>::Error>`
|
||||
// assert_future::<Result<(), Self::Error>, _>(SendAll::new(self, stream))
|
||||
SendAll::new(self, stream)
|
||||
}
|
||||
|
||||
/// Wrap this sink in an `Either` sink, making it the left-hand variant
|
||||
/// of that `Either`.
|
||||
///
|
||||
/// This can be used in combination with the `right_sink` method to write `if`
|
||||
/// statements that evaluate to different streams in different branches.
|
||||
fn left_sink<Si2>(self) -> Either<Self, Si2>
|
||||
where
|
||||
Si2: Sink<Item, Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_sink::<Item, Self::Error, _>(Either::Left(self))
|
||||
}
|
||||
|
||||
/// Wrap this stream in an `Either` stream, making it the right-hand variant
|
||||
/// of that `Either`.
|
||||
///
|
||||
/// This can be used in combination with the `left_sink` method to write `if`
|
||||
/// statements that evaluate to different streams in different branches.
|
||||
fn right_sink<Si1>(self) -> Either<Si1, Self>
|
||||
where
|
||||
Si1: Sink<Item, Error = Self::Error>,
|
||||
Self: Sized,
|
||||
{
|
||||
assert_sink::<Item, Self::Error, _>(Either::Right(self))
|
||||
}
|
||||
|
||||
/// Wraps a [`Sink`] into a sink compatible with libraries using
|
||||
/// futures 0.1 `Sink`. Requires the `compat` feature to be enabled.
|
||||
#[cfg(feature = "compat")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "compat")))]
|
||||
fn compat(self) -> CompatSink<Self, Item>
|
||||
where
|
||||
Self: Sized + Unpin,
|
||||
{
|
||||
CompatSink::new(self)
|
||||
}
|
||||
|
||||
/// A convenience method for calling [`Sink::poll_ready`] on [`Unpin`]
|
||||
/// sink types.
|
||||
fn poll_ready_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
Pin::new(self).poll_ready(cx)
|
||||
}
|
||||
|
||||
/// A convenience method for calling [`Sink::start_send`] on [`Unpin`]
|
||||
/// sink types.
|
||||
fn start_send_unpin(&mut self, item: Item) -> Result<(), Self::Error>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
Pin::new(self).start_send(item)
|
||||
}
|
||||
|
||||
/// A convenience method for calling [`Sink::poll_flush`] on [`Unpin`]
|
||||
/// sink types.
|
||||
fn poll_flush_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
Pin::new(self).poll_flush(cx)
|
||||
}
|
||||
|
||||
/// A convenience method for calling [`Sink::poll_close`] on [`Unpin`]
|
||||
/// sink types.
|
||||
fn poll_close_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>
|
||||
where
|
||||
Self: Unpin,
|
||||
{
|
||||
Pin::new(self).poll_close(cx)
|
||||
}
|
||||
}
|
||||
|
||||
// Just a helper function to ensure the sinks we're returning all have the
|
||||
// right implementations.
|
||||
pub(crate) fn assert_sink<T, E, S>(sink: S) -> S
|
||||
where
|
||||
S: Sink<T, Error = E>,
|
||||
{
|
||||
sink
|
||||
}
|
||||
41
zeroidc/vendor/futures-util/src/sink/send.rs
vendored
Normal file
41
zeroidc/vendor/futures-util/src/sink/send.rs
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
use super::Feed;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
|
||||
/// Future for the [`send`](super::SinkExt::send) method.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Send<'a, Si: ?Sized, Item> {
|
||||
feed: Feed<'a, Si, Item>,
|
||||
}
|
||||
|
||||
// Pinning is never projected to children
|
||||
impl<Si: Unpin + ?Sized, Item> Unpin for Send<'_, Si, Item> {}
|
||||
|
||||
impl<'a, Si: Sink<Item> + Unpin + ?Sized, Item> Send<'a, Si, Item> {
|
||||
pub(super) fn new(sink: &'a mut Si, item: Item) -> Self {
|
||||
Self { feed: Feed::new(sink, item) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si: Sink<Item> + Unpin + ?Sized, Item> Future for Send<'_, Si, Item> {
|
||||
type Output = Result<(), Si::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
|
||||
if this.feed.is_item_pending() {
|
||||
ready!(Pin::new(&mut this.feed).poll(cx))?;
|
||||
debug_assert!(!this.feed.is_item_pending());
|
||||
}
|
||||
|
||||
// we're done sending the item, but want to block on flushing the
|
||||
// sink
|
||||
ready!(this.feed.sink_pin_mut().poll_flush(cx))?;
|
||||
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
100
zeroidc/vendor/futures-util/src/sink/send_all.rs
vendored
Normal file
100
zeroidc/vendor/futures-util/src/sink/send_all.rs
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
use crate::stream::{Fuse, StreamExt, TryStreamExt};
|
||||
use core::fmt;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::stream::{Stream, TryStream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
|
||||
/// Future for the [`send_all`](super::SinkExt::send_all) method.
|
||||
#[allow(explicit_outlives_requirements)] // https://github.com/rust-lang/rust/issues/60993
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct SendAll<'a, Si, St>
|
||||
where
|
||||
Si: ?Sized,
|
||||
St: ?Sized + TryStream,
|
||||
{
|
||||
sink: &'a mut Si,
|
||||
stream: Fuse<&'a mut St>,
|
||||
buffered: Option<St::Ok>,
|
||||
}
|
||||
|
||||
impl<Si, St> fmt::Debug for SendAll<'_, Si, St>
|
||||
where
|
||||
Si: fmt::Debug + ?Sized,
|
||||
St: fmt::Debug + ?Sized + TryStream,
|
||||
St::Ok: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SendAll")
|
||||
.field("sink", &self.sink)
|
||||
.field("stream", &self.stream)
|
||||
.field("buffered", &self.buffered)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// Pinning is never projected to any fields
|
||||
impl<Si, St> Unpin for SendAll<'_, Si, St>
|
||||
where
|
||||
Si: Unpin + ?Sized,
|
||||
St: TryStream + Unpin + ?Sized,
|
||||
{
|
||||
}
|
||||
|
||||
impl<'a, Si, St, Ok, Error> SendAll<'a, Si, St>
|
||||
where
|
||||
Si: Sink<Ok, Error = Error> + Unpin + ?Sized,
|
||||
St: TryStream<Ok = Ok, Error = Error> + Stream + Unpin + ?Sized,
|
||||
{
|
||||
pub(super) fn new(sink: &'a mut Si, stream: &'a mut St) -> Self {
|
||||
Self { sink, stream: stream.fuse(), buffered: None }
|
||||
}
|
||||
|
||||
fn try_start_send(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
item: St::Ok,
|
||||
) -> Poll<Result<(), Si::Error>> {
|
||||
debug_assert!(self.buffered.is_none());
|
||||
match Pin::new(&mut self.sink).poll_ready(cx)? {
|
||||
Poll::Ready(()) => Poll::Ready(Pin::new(&mut self.sink).start_send(item)),
|
||||
Poll::Pending => {
|
||||
self.buffered = Some(item);
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, St, Ok, Error> Future for SendAll<'_, Si, St>
|
||||
where
|
||||
Si: Sink<Ok, Error = Error> + Unpin + ?Sized,
|
||||
St: Stream<Item = Result<Ok, Error>> + Unpin + ?Sized,
|
||||
{
|
||||
type Output = Result<(), Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
// If we've got an item buffered already, we need to write it to the
|
||||
// sink before we can do anything else
|
||||
if let Some(item) = this.buffered.take() {
|
||||
ready!(this.try_start_send(cx, item))?
|
||||
}
|
||||
|
||||
loop {
|
||||
match this.stream.try_poll_next_unpin(cx)? {
|
||||
Poll::Ready(Some(item)) => ready!(this.try_start_send(cx, item))?,
|
||||
Poll::Ready(None) => {
|
||||
ready!(Pin::new(&mut this.sink).poll_flush(cx))?;
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
Poll::Pending => {
|
||||
ready!(Pin::new(&mut this.sink).poll_flush(cx))?;
|
||||
return Poll::Pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
86
zeroidc/vendor/futures-util/src/sink/unfold.rs
vendored
Normal file
86
zeroidc/vendor/futures-util/src/sink/unfold.rs
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
use super::assert_sink;
|
||||
use crate::unfold_state::UnfoldState;
|
||||
use core::{future::Future, pin::Pin};
|
||||
use futures_core::ready;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`unfold`] function.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct Unfold<T, F, R> {
|
||||
function: F,
|
||||
#[pin]
|
||||
state: UnfoldState<T, R>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a sink from a function which processes one item at a time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # futures::executor::block_on(async {
|
||||
/// use futures::sink::{self, SinkExt};
|
||||
///
|
||||
/// let unfold = sink::unfold(0, |mut sum, i: i32| {
|
||||
/// async move {
|
||||
/// sum += i;
|
||||
/// eprintln!("{}", i);
|
||||
/// Ok::<_, futures::never::Never>(sum)
|
||||
/// }
|
||||
/// });
|
||||
/// futures::pin_mut!(unfold);
|
||||
/// unfold.send(5).await?;
|
||||
/// # Ok::<(), futures::never::Never>(()) }).unwrap();
|
||||
/// ```
|
||||
pub fn unfold<T, F, R, Item, E>(init: T, function: F) -> Unfold<T, F, R>
|
||||
where
|
||||
F: FnMut(T, Item) -> R,
|
||||
R: Future<Output = Result<T, E>>,
|
||||
{
|
||||
assert_sink::<Item, E, _>(Unfold { function, state: UnfoldState::Value { value: init } })
|
||||
}
|
||||
|
||||
impl<T, F, R, Item, E> Sink<Item> for Unfold<T, F, R>
|
||||
where
|
||||
F: FnMut(T, Item) -> R,
|
||||
R: Future<Output = Result<T, E>>,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.poll_flush(cx)
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
|
||||
let mut this = self.project();
|
||||
let future = match this.state.as_mut().take_value() {
|
||||
Some(value) => (this.function)(value, item),
|
||||
None => panic!("start_send called without poll_ready being called first"),
|
||||
};
|
||||
this.state.set(UnfoldState::Future { future });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let mut this = self.project();
|
||||
Poll::Ready(if let Some(future) = this.state.as_mut().project_future() {
|
||||
match ready!(future.poll(cx)) {
|
||||
Ok(state) => {
|
||||
this.state.set(UnfoldState::Value { value: state });
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.poll_flush(cx)
|
||||
}
|
||||
}
|
||||
134
zeroidc/vendor/futures-util/src/sink/with.rs
vendored
Normal file
134
zeroidc/vendor/futures-util/src/sink/with.rs
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`with`](super::SinkExt::with) method.
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct With<Si, Item, U, Fut, F> {
|
||||
#[pin]
|
||||
sink: Si,
|
||||
f: F,
|
||||
#[pin]
|
||||
state: Option<Fut>,
|
||||
_phantom: PhantomData<fn(U) -> Item>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, Fut, F> fmt::Debug for With<Si, Item, U, Fut, F>
|
||||
where
|
||||
Si: fmt::Debug,
|
||||
Fut: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("With").field("sink", &self.sink).field("state", &self.state).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, Fut, F> With<Si, Item, U, Fut, F>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
F: FnMut(U) -> Fut,
|
||||
Fut: Future,
|
||||
{
|
||||
pub(super) fn new<E>(sink: Si, f: F) -> Self
|
||||
where
|
||||
Fut: Future<Output = Result<Item, E>>,
|
||||
E: From<Si::Error>,
|
||||
{
|
||||
Self { state: None, sink, f, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, Fut, F> Clone for With<Si, Item, U, Fut, F>
|
||||
where
|
||||
Si: Clone,
|
||||
F: Clone,
|
||||
Fut: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
state: self.state.clone(),
|
||||
sink: self.sink.clone(),
|
||||
f: self.f.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forwarding impl of Stream from the underlying sink
|
||||
impl<S, Item, U, Fut, F> Stream for With<S, Item, U, Fut, F>
|
||||
where
|
||||
S: Stream + Sink<Item>,
|
||||
F: FnMut(U) -> Fut,
|
||||
Fut: Future,
|
||||
{
|
||||
type Item = S::Item;
|
||||
|
||||
delegate_stream!(sink);
|
||||
}
|
||||
|
||||
impl<Si, Item, U, Fut, F, E> With<Si, Item, U, Fut, F>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
F: FnMut(U) -> Fut,
|
||||
Fut: Future<Output = Result<Item, E>>,
|
||||
E: From<Si::Error>,
|
||||
{
|
||||
delegate_access_inner!(sink, Si, ());
|
||||
|
||||
/// Completes the processing of previous item if any.
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), E>> {
|
||||
let mut this = self.project();
|
||||
|
||||
let item = match this.state.as_mut().as_pin_mut() {
|
||||
None => return Poll::Ready(Ok(())),
|
||||
Some(fut) => ready!(fut.poll(cx))?,
|
||||
};
|
||||
this.state.set(None);
|
||||
this.sink.start_send(item)?;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, Fut, F, E> Sink<U> for With<Si, Item, U, Fut, F>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
F: FnMut(U) -> Fut,
|
||||
Fut: Future<Output = Result<Item, E>>,
|
||||
E: From<Si::Error>,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll(cx))?;
|
||||
ready!(self.project().sink.poll_ready(cx)?);
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: U) -> Result<(), Self::Error> {
|
||||
let mut this = self.project();
|
||||
|
||||
assert!(this.state.is_none());
|
||||
this.state.set(Some((this.f)(item)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll(cx))?;
|
||||
ready!(self.project().sink.poll_flush(cx)?);
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll(cx))?;
|
||||
ready!(self.project().sink.poll_close(cx)?);
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
127
zeroidc/vendor/futures-util/src/sink/with_flat_map.rs
vendored
Normal file
127
zeroidc/vendor/futures-util/src/sink/with_flat_map.rs
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use futures_core::ready;
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_sink::Sink;
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
/// Sink for the [`with_flat_map`](super::SinkExt::with_flat_map) method.
|
||||
#[must_use = "sinks do nothing unless polled"]
|
||||
pub struct WithFlatMap<Si, Item, U, St, F> {
|
||||
#[pin]
|
||||
sink: Si,
|
||||
f: F,
|
||||
#[pin]
|
||||
stream: Option<St>,
|
||||
buffer: Option<Item>,
|
||||
_marker: PhantomData<fn(U)>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, St, F> fmt::Debug for WithFlatMap<Si, Item, U, St, F>
|
||||
where
|
||||
Si: fmt::Debug,
|
||||
St: fmt::Debug,
|
||||
Item: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("WithFlatMap")
|
||||
.field("sink", &self.sink)
|
||||
.field("stream", &self.stream)
|
||||
.field("buffer", &self.buffer)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, St, F> WithFlatMap<Si, Item, U, St, F>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
F: FnMut(U) -> St,
|
||||
St: Stream<Item = Result<Item, Si::Error>>,
|
||||
{
|
||||
pub(super) fn new(sink: Si, f: F) -> Self {
|
||||
Self { sink, f, stream: None, buffer: None, _marker: PhantomData }
|
||||
}
|
||||
|
||||
delegate_access_inner!(sink, Si, ());
|
||||
|
||||
fn try_empty_stream(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Si::Error>> {
|
||||
let mut this = self.project();
|
||||
|
||||
if this.buffer.is_some() {
|
||||
ready!(this.sink.as_mut().poll_ready(cx))?;
|
||||
let item = this.buffer.take().unwrap();
|
||||
this.sink.as_mut().start_send(item)?;
|
||||
}
|
||||
if let Some(mut some_stream) = this.stream.as_mut().as_pin_mut() {
|
||||
while let Some(item) = ready!(some_stream.as_mut().poll_next(cx)?) {
|
||||
match this.sink.as_mut().poll_ready(cx)? {
|
||||
Poll::Ready(()) => this.sink.as_mut().start_send(item)?,
|
||||
Poll::Pending => {
|
||||
*this.buffer = Some(item);
|
||||
return Poll::Pending;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
this.stream.set(None);
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
// Forwarding impl of Stream from the underlying sink
|
||||
impl<S, Item, U, St, F> Stream for WithFlatMap<S, Item, U, St, F>
|
||||
where
|
||||
S: Stream + Sink<Item>,
|
||||
F: FnMut(U) -> St,
|
||||
St: Stream<Item = Result<Item, S::Error>>,
|
||||
{
|
||||
type Item = S::Item;
|
||||
|
||||
delegate_stream!(sink);
|
||||
}
|
||||
|
||||
impl<S, Item, U, St, F> FusedStream for WithFlatMap<S, Item, U, St, F>
|
||||
where
|
||||
S: FusedStream + Sink<Item>,
|
||||
F: FnMut(U) -> St,
|
||||
St: Stream<Item = Result<Item, S::Error>>,
|
||||
{
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.sink.is_terminated()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Si, Item, U, St, F> Sink<U> for WithFlatMap<Si, Item, U, St, F>
|
||||
where
|
||||
Si: Sink<Item>,
|
||||
F: FnMut(U) -> St,
|
||||
St: Stream<Item = Result<Item, Si::Error>>,
|
||||
{
|
||||
type Error = Si::Error;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.try_empty_stream(cx)
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: U) -> Result<(), Self::Error> {
|
||||
let mut this = self.project();
|
||||
|
||||
assert!(this.stream.is_none());
|
||||
this.stream.set(Some((this.f)(item)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().try_empty_stream(cx)?);
|
||||
self.project().sink.poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().try_empty_stream(cx)?);
|
||||
self.project().sink.poll_close(cx)
|
||||
}
|
||||
}
|
||||
19
zeroidc/vendor/futures-util/src/stream/abortable.rs
vendored
Normal file
19
zeroidc/vendor/futures-util/src/stream/abortable.rs
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
use super::assert_stream;
|
||||
use crate::stream::{AbortHandle, Abortable};
|
||||
use crate::Stream;
|
||||
|
||||
/// Creates a new `Abortable` stream 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<St>(stream: St) -> (Abortable<St>, AbortHandle)
|
||||
where
|
||||
St: Stream,
|
||||
{
|
||||
let (handle, reg) = AbortHandle::new_pair();
|
||||
let abortable = assert_stream::<St::Item, _>(Abortable::new(stream, reg));
|
||||
(abortable, handle)
|
||||
}
|
||||
45
zeroidc/vendor/futures-util/src/stream/empty.rs
vendored
Normal file
45
zeroidc/vendor/futures-util/src/stream/empty.rs
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
use super::assert_stream;
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
|
||||
/// Stream for the [`empty`] function.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "streams do nothing unless polled"]
|
||||
pub struct Empty<T> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
/// Creates a stream which contains no elements.
|
||||
///
|
||||
/// The returned stream will always return `Ready(None)` when polled.
|
||||
pub fn empty<T>() -> Empty<T> {
|
||||
assert_stream::<T, _>(Empty { _phantom: PhantomData })
|
||||
}
|
||||
|
||||
impl<T> Unpin for Empty<T> {}
|
||||
|
||||
impl<T> FusedStream for Empty<T> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Stream for Empty<T> {
|
||||
type Item = T;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
Poll::Ready(None)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Empty<T> {
|
||||
fn clone(&self) -> Self {
|
||||
empty()
|
||||
}
|
||||
}
|
||||
220
zeroidc/vendor/futures-util/src/stream/futures_ordered.rs
vendored
Normal file
220
zeroidc/vendor/futures-util/src/stream/futures_ordered.rs
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
use crate::stream::{FuturesUnordered, StreamExt};
|
||||
use alloc::collections::binary_heap::{BinaryHeap, PeekMut};
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::FromIterator;
|
||||
use core::pin::Pin;
|
||||
use futures_core::future::Future;
|
||||
use futures_core::ready;
|
||||
use futures_core::stream::Stream;
|
||||
use futures_core::{
|
||||
task::{Context, Poll},
|
||||
FusedStream,
|
||||
};
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
pin_project! {
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
struct OrderWrapper<T> {
|
||||
#[pin]
|
||||
data: T, // A future or a future's output
|
||||
index: usize,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for OrderWrapper<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.index == other.index
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for OrderWrapper<T> {}
|
||||
|
||||
impl<T> PartialOrd for OrderWrapper<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Ord for OrderWrapper<T> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
// BinaryHeap is a max heap, so compare backwards here.
|
||||
other.index.cmp(&self.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for OrderWrapper<T>
|
||||
where
|
||||
T: Future,
|
||||
{
|
||||
type Output = OrderWrapper<T::Output>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let index = self.index;
|
||||
self.project().data.poll(cx).map(|output| OrderWrapper { data: output, index })
|
||||
}
|
||||
}
|
||||
|
||||
/// An unbounded queue of futures.
|
||||
///
|
||||
/// This "combinator" is similar to `FuturesUnordered`, but it imposes an order
|
||||
/// on top of the set of futures. While futures in the set will race to
|
||||
/// completion in parallel, results will only be returned in the order their
|
||||
/// originating futures were added to the queue.
|
||||
///
|
||||
/// Futures are pushed into this queue and their realized values are yielded in
|
||||
/// order. This structure is optimized to manage a large number of futures.
|
||||
/// Futures managed by `FuturesOrdered` will only be polled when they generate
|
||||
/// notifications. This reduces the required amount of work needed to coordinate
|
||||
/// large numbers of futures.
|
||||
///
|
||||
/// When a `FuturesOrdered` is first created, it does not contain any futures.
|
||||
/// Calling `poll` in this state will result in `Poll::Ready(None))` to be
|
||||
/// returned. Futures are submitted to the queue using `push`; however, the
|
||||
/// future will **not** be polled at this point. `FuturesOrdered` will only
|
||||
/// poll managed futures when `FuturesOrdered::poll` is called. As such, it
|
||||
/// is important to call `poll` after pushing new futures.
|
||||
///
|
||||
/// If `FuturesOrdered::poll` returns `Poll::Ready(None)` this means that
|
||||
/// the queue is currently not managing any futures. A future may be submitted
|
||||
/// to the queue at a later time. At that point, a call to
|
||||
/// `FuturesOrdered::poll` will either return the future's resolved value
|
||||
/// **or** `Poll::Pending` if the future has not yet completed. When
|
||||
/// multiple futures are submitted to the queue, `FuturesOrdered::poll` will
|
||||
/// return `Poll::Pending` until the first future completes, even if
|
||||
/// some of the later futures have already completed.
|
||||
///
|
||||
/// Note that you can create a ready-made `FuturesOrdered` via the
|
||||
/// [`collect`](Iterator::collect) method, or you can start with an empty queue
|
||||
/// with the `FuturesOrdered::new` constructor.
|
||||
///
|
||||
/// This type is only available when the `std` or `alloc` feature of this
|
||||
/// library is activated, and it is activated by default.
|
||||
#[must_use = "streams do nothing unless polled"]
|
||||
pub struct FuturesOrdered<T: Future> {
|
||||
in_progress_queue: FuturesUnordered<OrderWrapper<T>>,
|
||||
queued_outputs: BinaryHeap<OrderWrapper<T::Output>>,
|
||||
next_incoming_index: usize,
|
||||
next_outgoing_index: usize,
|
||||
}
|
||||
|
||||
impl<T: Future> Unpin for FuturesOrdered<T> {}
|
||||
|
||||
impl<Fut: Future> FuturesOrdered<Fut> {
|
||||
/// Constructs a new, empty `FuturesOrdered`
|
||||
///
|
||||
/// The returned `FuturesOrdered` does not contain any futures and, in this
|
||||
/// state, `FuturesOrdered::poll_next` will return `Poll::Ready(None)`.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
in_progress_queue: FuturesUnordered::new(),
|
||||
queued_outputs: BinaryHeap::new(),
|
||||
next_incoming_index: 0,
|
||||
next_outgoing_index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of futures contained in the queue.
|
||||
///
|
||||
/// This represents the total number of in-flight futures, both
|
||||
/// those currently processing and those that have completed but
|
||||
/// which are waiting for earlier futures to complete.
|
||||
pub fn len(&self) -> usize {
|
||||
self.in_progress_queue.len() + self.queued_outputs.len()
|
||||
}
|
||||
|
||||
/// Returns `true` if the queue contains no futures
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.in_progress_queue.is_empty() && self.queued_outputs.is_empty()
|
||||
}
|
||||
|
||||
/// Push a future into the queue.
|
||||
///
|
||||
/// This function submits the given future to the internal set for managing.
|
||||
/// This function will not call `poll` on the submitted future. The caller
|
||||
/// must ensure that `FuturesOrdered::poll` is called in order to receive
|
||||
/// task notifications.
|
||||
pub fn push(&mut self, future: Fut) {
|
||||
let wrapped = OrderWrapper { data: future, index: self.next_incoming_index };
|
||||
self.next_incoming_index += 1;
|
||||
self.in_progress_queue.push(wrapped);
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Default for FuturesOrdered<Fut> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Stream for FuturesOrdered<Fut> {
|
||||
type Item = Fut::Output;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let this = &mut *self;
|
||||
|
||||
// Check to see if we've already received the next value
|
||||
if let Some(next_output) = this.queued_outputs.peek_mut() {
|
||||
if next_output.index == this.next_outgoing_index {
|
||||
this.next_outgoing_index += 1;
|
||||
return Poll::Ready(Some(PeekMut::pop(next_output).data));
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match ready!(this.in_progress_queue.poll_next_unpin(cx)) {
|
||||
Some(output) => {
|
||||
if output.index == this.next_outgoing_index {
|
||||
this.next_outgoing_index += 1;
|
||||
return Poll::Ready(Some(output.data));
|
||||
} else {
|
||||
this.queued_outputs.push(output)
|
||||
}
|
||||
}
|
||||
None => return Poll::Ready(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len();
|
||||
(len, Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Debug for FuturesOrdered<Fut> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FuturesOrdered {{ ... }}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> FromIterator<Fut> for FuturesOrdered<Fut> {
|
||||
fn from_iter<T>(iter: T) -> Self
|
||||
where
|
||||
T: IntoIterator<Item = Fut>,
|
||||
{
|
||||
let acc = Self::new();
|
||||
iter.into_iter().fold(acc, |mut acc, item| {
|
||||
acc.push(item);
|
||||
acc
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> FusedStream for FuturesOrdered<Fut> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.in_progress_queue.is_terminated() && self.queued_outputs.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Extend<Fut> for FuturesOrdered<Fut> {
|
||||
fn extend<I>(&mut self, iter: I)
|
||||
where
|
||||
I: IntoIterator<Item = Fut>,
|
||||
{
|
||||
for item in iter {
|
||||
self.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
zeroidc/vendor/futures-util/src/stream/futures_unordered/abort.rs
vendored
Normal file
12
zeroidc/vendor/futures-util/src/stream/futures_unordered/abort.rs
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
pub(super) fn abort(s: &str) -> ! {
|
||||
struct DoublePanic;
|
||||
|
||||
impl Drop for DoublePanic {
|
||||
fn drop(&mut self) {
|
||||
panic!("panicking twice to abort the program");
|
||||
}
|
||||
}
|
||||
|
||||
let _bomb = DoublePanic;
|
||||
panic!("{}", s);
|
||||
}
|
||||
168
zeroidc/vendor/futures-util/src/stream/futures_unordered/iter.rs
vendored
Normal file
168
zeroidc/vendor/futures-util/src/stream/futures_unordered/iter.rs
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
use super::task::Task;
|
||||
use super::FuturesUnordered;
|
||||
use core::marker::PhantomData;
|
||||
use core::pin::Pin;
|
||||
use core::sync::atomic::Ordering::Relaxed;
|
||||
|
||||
/// Mutable iterator over all futures in the unordered set.
|
||||
#[derive(Debug)]
|
||||
pub struct IterPinMut<'a, Fut> {
|
||||
pub(super) task: *const Task<Fut>,
|
||||
pub(super) len: usize,
|
||||
pub(super) _marker: PhantomData<&'a mut FuturesUnordered<Fut>>,
|
||||
}
|
||||
|
||||
/// Mutable iterator over all futures in the unordered set.
|
||||
#[derive(Debug)]
|
||||
pub struct IterMut<'a, Fut: Unpin>(pub(super) IterPinMut<'a, Fut>);
|
||||
|
||||
/// Immutable iterator over all futures in the unordered set.
|
||||
#[derive(Debug)]
|
||||
pub struct IterPinRef<'a, Fut> {
|
||||
pub(super) task: *const Task<Fut>,
|
||||
pub(super) len: usize,
|
||||
pub(super) pending_next_all: *mut Task<Fut>,
|
||||
pub(super) _marker: PhantomData<&'a FuturesUnordered<Fut>>,
|
||||
}
|
||||
|
||||
/// Immutable iterator over all the futures in the unordered set.
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a, Fut: Unpin>(pub(super) IterPinRef<'a, Fut>);
|
||||
|
||||
/// Owned iterator over all futures in the unordered set.
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<Fut: Unpin> {
|
||||
pub(super) len: usize,
|
||||
pub(super) inner: FuturesUnordered<Fut>,
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> Iterator for IntoIter<Fut> {
|
||||
type Item = Fut;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// `head_all` can be accessed directly and we don't need to spin on
|
||||
// `Task::next_all` since we have exclusive access to the set.
|
||||
let task = self.inner.head_all.get_mut();
|
||||
|
||||
if (*task).is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// Moving out of the future is safe because it is `Unpin`
|
||||
let future = (*(**task).future.get()).take().unwrap();
|
||||
|
||||
// Mutable access to a previously shared `FuturesUnordered` implies
|
||||
// that the other threads already released the object before the
|
||||
// current thread acquired it, so relaxed ordering can be used and
|
||||
// valid `next_all` checks can be skipped.
|
||||
let next = (**task).next_all.load(Relaxed);
|
||||
*task = next;
|
||||
self.len -= 1;
|
||||
Some(future)
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> ExactSizeIterator for IntoIter<Fut> {}
|
||||
|
||||
impl<'a, Fut> Iterator for IterPinMut<'a, Fut> {
|
||||
type Item = Pin<&'a mut Fut>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.task.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let future = (*(*self.task).future.get()).as_mut().unwrap();
|
||||
|
||||
// Mutable access to a previously shared `FuturesUnordered` implies
|
||||
// that the other threads already released the object before the
|
||||
// current thread acquired it, so relaxed ordering can be used and
|
||||
// valid `next_all` checks can be skipped.
|
||||
let next = (*self.task).next_all.load(Relaxed);
|
||||
self.task = next;
|
||||
self.len -= 1;
|
||||
Some(Pin::new_unchecked(future))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> ExactSizeIterator for IterPinMut<'_, Fut> {}
|
||||
|
||||
impl<'a, Fut: Unpin> Iterator for IterMut<'a, Fut> {
|
||||
type Item = &'a mut Fut;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next().map(Pin::get_mut)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> ExactSizeIterator for IterMut<'_, Fut> {}
|
||||
|
||||
impl<'a, Fut> Iterator for IterPinRef<'a, Fut> {
|
||||
type Item = Pin<&'a Fut>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.task.is_null() {
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let future = (*(*self.task).future.get()).as_ref().unwrap();
|
||||
|
||||
// Relaxed ordering can be used since acquire ordering when
|
||||
// `head_all` was initially read for this iterator implies acquire
|
||||
// ordering for all previously inserted nodes (and we don't need to
|
||||
// read `len_all` again for any other nodes).
|
||||
let next = (*self.task).spin_next_all(self.pending_next_all, Relaxed);
|
||||
self.task = next;
|
||||
self.len -= 1;
|
||||
Some(Pin::new_unchecked(future))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> ExactSizeIterator for IterPinRef<'_, Fut> {}
|
||||
|
||||
impl<'a, Fut: Unpin> Iterator for Iter<'a, Fut> {
|
||||
type Item = &'a Fut;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next().map(Pin::get_ref)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> ExactSizeIterator for Iter<'_, Fut> {}
|
||||
|
||||
// SAFETY: we do nothing thread-local and there is no interior mutability,
|
||||
// so the usual structural `Send`/`Sync` apply.
|
||||
unsafe impl<Fut: Send> Send for IterPinRef<'_, Fut> {}
|
||||
unsafe impl<Fut: Sync> Sync for IterPinRef<'_, Fut> {}
|
||||
|
||||
unsafe impl<Fut: Send> Send for IterPinMut<'_, Fut> {}
|
||||
unsafe impl<Fut: Sync> Sync for IterPinMut<'_, Fut> {}
|
||||
|
||||
unsafe impl<Fut: Send + Unpin> Send for IntoIter<Fut> {}
|
||||
unsafe impl<Fut: Sync + Unpin> Sync for IntoIter<Fut> {}
|
||||
657
zeroidc/vendor/futures-util/src/stream/futures_unordered/mod.rs
vendored
Normal file
657
zeroidc/vendor/futures-util/src/stream/futures_unordered/mod.rs
vendored
Normal file
@@ -0,0 +1,657 @@
|
||||
//! An unbounded set of futures.
|
||||
//!
|
||||
//! This module is only available when the `std` or `alloc` feature of this
|
||||
//! library is activated, and it is activated by default.
|
||||
|
||||
use crate::task::AtomicWaker;
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use core::cell::UnsafeCell;
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::FromIterator;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
use core::pin::Pin;
|
||||
use core::ptr;
|
||||
use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst};
|
||||
use core::sync::atomic::{AtomicBool, AtomicPtr};
|
||||
use futures_core::future::Future;
|
||||
use futures_core::stream::{FusedStream, Stream};
|
||||
use futures_core::task::{Context, Poll};
|
||||
use futures_task::{FutureObj, LocalFutureObj, LocalSpawn, Spawn, SpawnError};
|
||||
|
||||
mod abort;
|
||||
|
||||
mod iter;
|
||||
pub use self::iter::{IntoIter, Iter, IterMut, IterPinMut, IterPinRef};
|
||||
|
||||
mod task;
|
||||
use self::task::Task;
|
||||
|
||||
mod ready_to_run_queue;
|
||||
use self::ready_to_run_queue::{Dequeue, ReadyToRunQueue};
|
||||
|
||||
/// A set of futures which may complete in any order.
|
||||
///
|
||||
/// This structure is optimized to manage a large number of futures.
|
||||
/// Futures managed by [`FuturesUnordered`] will only be polled when they
|
||||
/// generate wake-up notifications. This reduces the required amount of work
|
||||
/// needed to poll large numbers of futures.
|
||||
///
|
||||
/// [`FuturesUnordered`] can be filled by [`collect`](Iterator::collect)ing an
|
||||
/// iterator of futures into a [`FuturesUnordered`], or by
|
||||
/// [`push`](FuturesUnordered::push)ing futures onto an existing
|
||||
/// [`FuturesUnordered`]. When new futures are added,
|
||||
/// [`poll_next`](Stream::poll_next) must be called in order to begin receiving
|
||||
/// wake-ups for new futures.
|
||||
///
|
||||
/// Note that you can create a ready-made [`FuturesUnordered`] via the
|
||||
/// [`collect`](Iterator::collect) method, or you can start with an empty set
|
||||
/// with the [`FuturesUnordered::new`] constructor.
|
||||
///
|
||||
/// This type is only available when the `std` or `alloc` feature of this
|
||||
/// library is activated, and it is activated by default.
|
||||
#[must_use = "streams do nothing unless polled"]
|
||||
pub struct FuturesUnordered<Fut> {
|
||||
ready_to_run_queue: Arc<ReadyToRunQueue<Fut>>,
|
||||
head_all: AtomicPtr<Task<Fut>>,
|
||||
is_terminated: AtomicBool,
|
||||
}
|
||||
|
||||
unsafe impl<Fut: Send> Send for FuturesUnordered<Fut> {}
|
||||
unsafe impl<Fut: Sync> Sync for FuturesUnordered<Fut> {}
|
||||
impl<Fut> Unpin for FuturesUnordered<Fut> {}
|
||||
|
||||
impl Spawn for FuturesUnordered<FutureObj<'_, ()>> {
|
||||
fn spawn_obj(&self, future_obj: FutureObj<'static, ()>) -> Result<(), SpawnError> {
|
||||
self.push(future_obj);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalSpawn for FuturesUnordered<LocalFutureObj<'_, ()>> {
|
||||
fn spawn_local_obj(&self, future_obj: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> {
|
||||
self.push(future_obj);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// FuturesUnordered is implemented using two linked lists. One which links all
|
||||
// futures managed by a `FuturesUnordered` and one that tracks futures that have
|
||||
// been scheduled for polling. The first linked list allows for thread safe
|
||||
// insertion of nodes at the head as well as forward iteration, but is otherwise
|
||||
// not thread safe and is only accessed by the thread that owns the
|
||||
// `FuturesUnordered` value for any other operations. The second linked list is
|
||||
// an implementation of the intrusive MPSC queue algorithm described by
|
||||
// 1024cores.net.
|
||||
//
|
||||
// When a future is submitted to the set, a task is allocated and inserted in
|
||||
// both linked lists. The next call to `poll_next` will (eventually) see this
|
||||
// task and call `poll` on the future.
|
||||
//
|
||||
// Before a managed future is polled, the current context's waker is replaced
|
||||
// with one that is aware of the specific future being run. This ensures that
|
||||
// wake-up notifications generated by that specific future are visible to
|
||||
// `FuturesUnordered`. When a wake-up notification is received, the task is
|
||||
// inserted into the ready to run queue, so that its future can be polled later.
|
||||
//
|
||||
// Each task is wrapped in an `Arc` and thereby atomically reference counted.
|
||||
// Also, each task contains an `AtomicBool` which acts as a flag that indicates
|
||||
// whether the task is currently inserted in the atomic queue. When a wake-up
|
||||
// notification is received, the task will only be inserted into the ready to
|
||||
// run queue if it isn't inserted already.
|
||||
|
||||
impl<Fut> Default for FuturesUnordered<Fut> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> FuturesUnordered<Fut> {
|
||||
/// Constructs a new, empty [`FuturesUnordered`].
|
||||
///
|
||||
/// The returned [`FuturesUnordered`] does not contain any futures.
|
||||
/// In this state, [`FuturesUnordered::poll_next`](Stream::poll_next) will
|
||||
/// return [`Poll::Ready(None)`](Poll::Ready).
|
||||
pub fn new() -> Self {
|
||||
let stub = Arc::new(Task {
|
||||
future: UnsafeCell::new(None),
|
||||
next_all: AtomicPtr::new(ptr::null_mut()),
|
||||
prev_all: UnsafeCell::new(ptr::null()),
|
||||
len_all: UnsafeCell::new(0),
|
||||
next_ready_to_run: AtomicPtr::new(ptr::null_mut()),
|
||||
queued: AtomicBool::new(true),
|
||||
ready_to_run_queue: Weak::new(),
|
||||
woken: AtomicBool::new(false),
|
||||
});
|
||||
let stub_ptr = Arc::as_ptr(&stub);
|
||||
let ready_to_run_queue = Arc::new(ReadyToRunQueue {
|
||||
waker: AtomicWaker::new(),
|
||||
head: AtomicPtr::new(stub_ptr as *mut _),
|
||||
tail: UnsafeCell::new(stub_ptr),
|
||||
stub,
|
||||
});
|
||||
|
||||
Self {
|
||||
head_all: AtomicPtr::new(ptr::null_mut()),
|
||||
ready_to_run_queue,
|
||||
is_terminated: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of futures contained in the set.
|
||||
///
|
||||
/// This represents the total number of in-flight futures.
|
||||
pub fn len(&self) -> usize {
|
||||
let (_, len) = self.atomic_load_head_and_len_all();
|
||||
len
|
||||
}
|
||||
|
||||
/// Returns `true` if the set contains no futures.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
// Relaxed ordering can be used here since we don't need to read from
|
||||
// the head pointer, only check whether it is null.
|
||||
self.head_all.load(Relaxed).is_null()
|
||||
}
|
||||
|
||||
/// Push a future into the set.
|
||||
///
|
||||
/// This method adds the given future to the set. This method will not
|
||||
/// call [`poll`](core::future::Future::poll) on the submitted future. The caller must
|
||||
/// ensure that [`FuturesUnordered::poll_next`](Stream::poll_next) is called
|
||||
/// in order to receive wake-up notifications for the given future.
|
||||
pub fn push(&self, future: Fut) {
|
||||
let task = Arc::new(Task {
|
||||
future: UnsafeCell::new(Some(future)),
|
||||
next_all: AtomicPtr::new(self.pending_next_all()),
|
||||
prev_all: UnsafeCell::new(ptr::null_mut()),
|
||||
len_all: UnsafeCell::new(0),
|
||||
next_ready_to_run: AtomicPtr::new(ptr::null_mut()),
|
||||
queued: AtomicBool::new(true),
|
||||
ready_to_run_queue: Arc::downgrade(&self.ready_to_run_queue),
|
||||
woken: AtomicBool::new(false),
|
||||
});
|
||||
|
||||
// Reset the `is_terminated` flag if we've previously marked ourselves
|
||||
// as terminated.
|
||||
self.is_terminated.store(false, Relaxed);
|
||||
|
||||
// Right now our task has a strong reference count of 1. We transfer
|
||||
// ownership of this reference count to our internal linked list
|
||||
// and we'll reclaim ownership through the `unlink` method below.
|
||||
let ptr = self.link(task);
|
||||
|
||||
// We'll need to get the future "into the system" to start tracking it,
|
||||
// e.g. getting its wake-up notifications going to us tracking which
|
||||
// futures are ready. To do that we unconditionally enqueue it for
|
||||
// polling here.
|
||||
self.ready_to_run_queue.enqueue(ptr);
|
||||
}
|
||||
|
||||
/// Returns an iterator that allows inspecting each future in the set.
|
||||
pub fn iter(&self) -> Iter<'_, Fut>
|
||||
where
|
||||
Fut: Unpin,
|
||||
{
|
||||
Iter(Pin::new(self).iter_pin_ref())
|
||||
}
|
||||
|
||||
/// Returns an iterator that allows inspecting each future in the set.
|
||||
pub fn iter_pin_ref(self: Pin<&Self>) -> IterPinRef<'_, Fut> {
|
||||
let (task, len) = self.atomic_load_head_and_len_all();
|
||||
let pending_next_all = self.pending_next_all();
|
||||
|
||||
IterPinRef { task, len, pending_next_all, _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Returns an iterator that allows modifying each future in the set.
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, Fut>
|
||||
where
|
||||
Fut: Unpin,
|
||||
{
|
||||
IterMut(Pin::new(self).iter_pin_mut())
|
||||
}
|
||||
|
||||
/// Returns an iterator that allows modifying each future in the set.
|
||||
pub fn iter_pin_mut(mut self: Pin<&mut Self>) -> IterPinMut<'_, Fut> {
|
||||
// `head_all` can be accessed directly and we don't need to spin on
|
||||
// `Task::next_all` since we have exclusive access to the set.
|
||||
let task = *self.head_all.get_mut();
|
||||
let len = if task.is_null() { 0 } else { unsafe { *(*task).len_all.get() } };
|
||||
|
||||
IterPinMut { task, len, _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Returns the current head node and number of futures in the list of all
|
||||
/// futures within a context where access is shared with other threads
|
||||
/// (mostly for use with the `len` and `iter_pin_ref` methods).
|
||||
fn atomic_load_head_and_len_all(&self) -> (*const Task<Fut>, usize) {
|
||||
let task = self.head_all.load(Acquire);
|
||||
let len = if task.is_null() {
|
||||
0
|
||||
} else {
|
||||
unsafe {
|
||||
(*task).spin_next_all(self.pending_next_all(), Acquire);
|
||||
*(*task).len_all.get()
|
||||
}
|
||||
};
|
||||
|
||||
(task, len)
|
||||
}
|
||||
|
||||
/// Releases the task. It destroys the future inside and either drops
|
||||
/// the `Arc<Task>` or transfers ownership to the ready to run queue.
|
||||
/// The task this method is called on must have been unlinked before.
|
||||
fn release_task(&mut self, task: Arc<Task<Fut>>) {
|
||||
// `release_task` must only be called on unlinked tasks
|
||||
debug_assert_eq!(task.next_all.load(Relaxed), self.pending_next_all());
|
||||
unsafe {
|
||||
debug_assert!((*task.prev_all.get()).is_null());
|
||||
}
|
||||
|
||||
// The future is done, try to reset the queued flag. This will prevent
|
||||
// `wake` from doing any work in the future
|
||||
let prev = task.queued.swap(true, SeqCst);
|
||||
|
||||
// Drop the future, even if it hasn't finished yet. This is safe
|
||||
// because we're dropping the future on the thread that owns
|
||||
// `FuturesUnordered`, which correctly tracks `Fut`'s lifetimes and
|
||||
// such.
|
||||
unsafe {
|
||||
// Set to `None` rather than `take()`ing to prevent moving the
|
||||
// future.
|
||||
*task.future.get() = None;
|
||||
}
|
||||
|
||||
// If the queued flag was previously set, then it means that this task
|
||||
// is still in our internal ready to run queue. We then transfer
|
||||
// ownership of our reference count to the ready to run queue, and it'll
|
||||
// come along and free it later, noticing that the future is `None`.
|
||||
//
|
||||
// If, however, the queued flag was *not* set then we're safe to
|
||||
// release our reference count on the task. The queued flag was set
|
||||
// above so all future `enqueue` operations will not actually
|
||||
// enqueue the task, so our task will never see the ready to run queue
|
||||
// again. The task itself will be deallocated once all reference counts
|
||||
// have been dropped elsewhere by the various wakers that contain it.
|
||||
if prev {
|
||||
mem::forget(task);
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a new task into the internal linked list.
|
||||
fn link(&self, task: Arc<Task<Fut>>) -> *const Task<Fut> {
|
||||
// `next_all` should already be reset to the pending state before this
|
||||
// function is called.
|
||||
debug_assert_eq!(task.next_all.load(Relaxed), self.pending_next_all());
|
||||
let ptr = Arc::into_raw(task);
|
||||
|
||||
// Atomically swap out the old head node to get the node that should be
|
||||
// assigned to `next_all`.
|
||||
let next = self.head_all.swap(ptr as *mut _, AcqRel);
|
||||
|
||||
unsafe {
|
||||
// Store the new list length in the new node.
|
||||
let new_len = if next.is_null() {
|
||||
1
|
||||
} else {
|
||||
// Make sure `next_all` has been written to signal that it is
|
||||
// safe to read `len_all`.
|
||||
(*next).spin_next_all(self.pending_next_all(), Acquire);
|
||||
*(*next).len_all.get() + 1
|
||||
};
|
||||
*(*ptr).len_all.get() = new_len;
|
||||
|
||||
// Write the old head as the next node pointer, signaling to other
|
||||
// threads that `len_all` and `next_all` are ready to read.
|
||||
(*ptr).next_all.store(next, Release);
|
||||
|
||||
// `prev_all` updates don't need to be synchronized, as the field is
|
||||
// only ever used after exclusive access has been acquired.
|
||||
if !next.is_null() {
|
||||
*(*next).prev_all.get() = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Remove the task from the linked list tracking all tasks currently
|
||||
/// managed by `FuturesUnordered`.
|
||||
/// This method is unsafe because it has be guaranteed that `task` is a
|
||||
/// valid pointer.
|
||||
unsafe fn unlink(&mut self, task: *const Task<Fut>) -> Arc<Task<Fut>> {
|
||||
// Compute the new list length now in case we're removing the head node
|
||||
// and won't be able to retrieve the correct length later.
|
||||
let head = *self.head_all.get_mut();
|
||||
debug_assert!(!head.is_null());
|
||||
let new_len = *(*head).len_all.get() - 1;
|
||||
|
||||
let task = Arc::from_raw(task);
|
||||
let next = task.next_all.load(Relaxed);
|
||||
let prev = *task.prev_all.get();
|
||||
task.next_all.store(self.pending_next_all(), Relaxed);
|
||||
*task.prev_all.get() = ptr::null_mut();
|
||||
|
||||
if !next.is_null() {
|
||||
*(*next).prev_all.get() = prev;
|
||||
}
|
||||
|
||||
if !prev.is_null() {
|
||||
(*prev).next_all.store(next, Relaxed);
|
||||
} else {
|
||||
*self.head_all.get_mut() = next;
|
||||
}
|
||||
|
||||
// Store the new list length in the head node.
|
||||
let head = *self.head_all.get_mut();
|
||||
if !head.is_null() {
|
||||
*(*head).len_all.get() = new_len;
|
||||
}
|
||||
|
||||
task
|
||||
}
|
||||
|
||||
/// Returns the reserved value for `Task::next_all` to indicate a pending
|
||||
/// assignment from the thread that inserted the task.
|
||||
///
|
||||
/// `FuturesUnordered::link` needs to update `Task` pointers in an order
|
||||
/// that ensures any iterators created on other threads can correctly
|
||||
/// traverse the entire `Task` list using the chain of `next_all` pointers.
|
||||
/// This could be solved with a compare-exchange loop that stores the
|
||||
/// current `head_all` in `next_all` and swaps out `head_all` with the new
|
||||
/// `Task` pointer if the head hasn't already changed. Under heavy thread
|
||||
/// contention, this compare-exchange loop could become costly.
|
||||
///
|
||||
/// An alternative is to initialize `next_all` to a reserved pending state
|
||||
/// first, perform an atomic swap on `head_all`, and finally update
|
||||
/// `next_all` with the old head node. Iterators will then either see the
|
||||
/// pending state value or the correct next node pointer, and can reload
|
||||
/// `next_all` as needed until the correct value is loaded. The number of
|
||||
/// retries needed (if any) would be small and will always be finite, so
|
||||
/// this should generally perform better than the compare-exchange loop.
|
||||
///
|
||||
/// A valid `Task` pointer in the `head_all` list is guaranteed to never be
|
||||
/// this value, so it is safe to use as a reserved value until the correct
|
||||
/// value can be written.
|
||||
fn pending_next_all(&self) -> *mut Task<Fut> {
|
||||
// The `ReadyToRunQueue` stub is never inserted into the `head_all`
|
||||
// list, and its pointer value will remain valid for the lifetime of
|
||||
// this `FuturesUnordered`, so we can make use of its value here.
|
||||
Arc::as_ptr(&self.ready_to_run_queue.stub) as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> Stream for FuturesUnordered<Fut> {
|
||||
type Item = Fut::Output;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let len = self.len();
|
||||
|
||||
// Keep track of how many child futures we have polled,
|
||||
// in case we want to forcibly yield.
|
||||
let mut polled = 0;
|
||||
let mut yielded = 0;
|
||||
|
||||
// Ensure `parent` is correctly set.
|
||||
self.ready_to_run_queue.waker.register(cx.waker());
|
||||
|
||||
loop {
|
||||
// Safety: &mut self guarantees the mutual exclusion `dequeue`
|
||||
// expects
|
||||
let task = match unsafe { self.ready_to_run_queue.dequeue() } {
|
||||
Dequeue::Empty => {
|
||||
if self.is_empty() {
|
||||
// We can only consider ourselves terminated once we
|
||||
// have yielded a `None`
|
||||
*self.is_terminated.get_mut() = true;
|
||||
return Poll::Ready(None);
|
||||
} else {
|
||||
return Poll::Pending;
|
||||
}
|
||||
}
|
||||
Dequeue::Inconsistent => {
|
||||
// At this point, it may be worth yielding the thread &
|
||||
// spinning a few times... but for now, just yield using the
|
||||
// task system.
|
||||
cx.waker().wake_by_ref();
|
||||
return Poll::Pending;
|
||||
}
|
||||
Dequeue::Data(task) => task,
|
||||
};
|
||||
|
||||
debug_assert!(task != self.ready_to_run_queue.stub());
|
||||
|
||||
// Safety:
|
||||
// - `task` is a valid pointer.
|
||||
// - We are the only thread that accesses the `UnsafeCell` that
|
||||
// contains the future
|
||||
let future = match unsafe { &mut *(*task).future.get() } {
|
||||
Some(future) => future,
|
||||
|
||||
// If the future has already gone away then we're just
|
||||
// cleaning out this task. See the comment in
|
||||
// `release_task` for more information, but we're basically
|
||||
// just taking ownership of our reference count here.
|
||||
None => {
|
||||
// This case only happens when `release_task` was called
|
||||
// for this task before and couldn't drop the task
|
||||
// because it was already enqueued in the ready to run
|
||||
// queue.
|
||||
|
||||
// Safety: `task` is a valid pointer
|
||||
let task = unsafe { Arc::from_raw(task) };
|
||||
|
||||
// Double check that the call to `release_task` really
|
||||
// happened. Calling it required the task to be unlinked.
|
||||
debug_assert_eq!(task.next_all.load(Relaxed), self.pending_next_all());
|
||||
unsafe {
|
||||
debug_assert!((*task.prev_all.get()).is_null());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Safety: `task` is a valid pointer
|
||||
let task = unsafe { self.unlink(task) };
|
||||
|
||||
// Unset queued flag: This must be done before polling to ensure
|
||||
// that the future's task gets rescheduled if it sends a wake-up
|
||||
// notification **during** the call to `poll`.
|
||||
let prev = task.queued.swap(false, SeqCst);
|
||||
assert!(prev);
|
||||
|
||||
// We're going to need to be very careful if the `poll`
|
||||
// method below panics. We need to (a) not leak memory and
|
||||
// (b) ensure that we still don't have any use-after-frees. To
|
||||
// manage this we do a few things:
|
||||
//
|
||||
// * A "bomb" is created which if dropped abnormally will call
|
||||
// `release_task`. That way we'll be sure the memory management
|
||||
// of the `task` is managed correctly. In particular
|
||||
// `release_task` will drop the future. This ensures that it is
|
||||
// dropped on this thread and not accidentally on a different
|
||||
// thread (bad).
|
||||
// * We unlink the task from our internal queue to preemptively
|
||||
// assume it'll panic, in which case we'll want to discard it
|
||||
// regardless.
|
||||
struct Bomb<'a, Fut> {
|
||||
queue: &'a mut FuturesUnordered<Fut>,
|
||||
task: Option<Arc<Task<Fut>>>,
|
||||
}
|
||||
|
||||
impl<Fut> Drop for Bomb<'_, Fut> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(task) = self.task.take() {
|
||||
self.queue.release_task(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut bomb = Bomb { task: Some(task), queue: &mut *self };
|
||||
|
||||
// Poll the underlying future with the appropriate waker
|
||||
// implementation. This is where a large bit of the unsafety
|
||||
// starts to stem from internally. The waker is basically just
|
||||
// our `Arc<Task<Fut>>` and can schedule the future for polling by
|
||||
// enqueuing itself in the ready to run queue.
|
||||
//
|
||||
// Critically though `Task<Fut>` won't actually access `Fut`, the
|
||||
// future, while it's floating around inside of wakers.
|
||||
// These structs will basically just use `Fut` to size
|
||||
// the internal allocation, appropriately accessing fields and
|
||||
// deallocating the task if need be.
|
||||
let res = {
|
||||
let task = bomb.task.as_ref().unwrap();
|
||||
// We are only interested in whether the future is awoken before it
|
||||
// finishes polling, so reset the flag here.
|
||||
task.woken.store(false, Relaxed);
|
||||
let waker = Task::waker_ref(task);
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
// Safety: We won't move the future ever again
|
||||
let future = unsafe { Pin::new_unchecked(future) };
|
||||
|
||||
future.poll(&mut cx)
|
||||
};
|
||||
polled += 1;
|
||||
|
||||
match res {
|
||||
Poll::Pending => {
|
||||
let task = bomb.task.take().unwrap();
|
||||
// If the future was awoken during polling, we assume
|
||||
// the future wanted to explicitly yield.
|
||||
yielded += task.woken.load(Relaxed) as usize;
|
||||
bomb.queue.link(task);
|
||||
|
||||
// If a future yields, we respect it and yield here.
|
||||
// If all futures have been polled, we also yield here to
|
||||
// avoid starving other tasks waiting on the executor.
|
||||
// (polling the same future twice per iteration may cause
|
||||
// the problem: https://github.com/rust-lang/futures-rs/pull/2333)
|
||||
if yielded >= 2 || polled == len {
|
||||
cx.waker().wake_by_ref();
|
||||
return Poll::Pending;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Poll::Ready(output) => return Poll::Ready(Some(output)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len();
|
||||
(len, Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Debug for FuturesUnordered<Fut> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "FuturesUnordered {{ ... }}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> FuturesUnordered<Fut> {
|
||||
/// Clears the set, removing all futures.
|
||||
pub fn clear(&mut self) {
|
||||
self.clear_head_all();
|
||||
|
||||
// we just cleared all the tasks, and we have &mut self, so this is safe.
|
||||
unsafe { self.ready_to_run_queue.clear() };
|
||||
|
||||
self.is_terminated.store(false, Relaxed);
|
||||
}
|
||||
|
||||
fn clear_head_all(&mut self) {
|
||||
while !self.head_all.get_mut().is_null() {
|
||||
let head = *self.head_all.get_mut();
|
||||
let task = unsafe { self.unlink(head) };
|
||||
self.release_task(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Drop for FuturesUnordered<Fut> {
|
||||
fn drop(&mut self) {
|
||||
// When a `FuturesUnordered` is dropped we want to drop all futures
|
||||
// associated with it. At the same time though there may be tons of
|
||||
// wakers flying around which contain `Task<Fut>` references
|
||||
// inside them. We'll let those naturally get deallocated.
|
||||
self.clear_head_all();
|
||||
|
||||
// Note that at this point we could still have a bunch of tasks in the
|
||||
// ready to run queue. None of those tasks, however, have futures
|
||||
// associated with them so they're safe to destroy on any thread. At
|
||||
// this point the `FuturesUnordered` struct, the owner of the one strong
|
||||
// reference to the ready to run queue will drop the strong reference.
|
||||
// At that point whichever thread releases the strong refcount last (be
|
||||
// it this thread or some other thread as part of an `upgrade`) will
|
||||
// clear out the ready to run queue and free all remaining tasks.
|
||||
//
|
||||
// While that freeing operation isn't guaranteed to happen here, it's
|
||||
// guaranteed to happen "promptly" as no more "blocking work" will
|
||||
// happen while there's a strong refcount held.
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Fut: Unpin> IntoIterator for &'a FuturesUnordered<Fut> {
|
||||
type Item = &'a Fut;
|
||||
type IntoIter = Iter<'a, Fut>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Fut: Unpin> IntoIterator for &'a mut FuturesUnordered<Fut> {
|
||||
type Item = &'a mut Fut;
|
||||
type IntoIter = IterMut<'a, Fut>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Unpin> IntoIterator for FuturesUnordered<Fut> {
|
||||
type Item = Fut;
|
||||
type IntoIter = IntoIter<Fut>;
|
||||
|
||||
fn into_iter(mut self) -> Self::IntoIter {
|
||||
// `head_all` can be accessed directly and we don't need to spin on
|
||||
// `Task::next_all` since we have exclusive access to the set.
|
||||
let task = *self.head_all.get_mut();
|
||||
let len = if task.is_null() { 0 } else { unsafe { *(*task).len_all.get() } };
|
||||
|
||||
IntoIter { len, inner: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> FromIterator<Fut> for FuturesUnordered<Fut> {
|
||||
fn from_iter<I>(iter: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Fut>,
|
||||
{
|
||||
let acc = Self::new();
|
||||
iter.into_iter().fold(acc, |acc, item| {
|
||||
acc.push(item);
|
||||
acc
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut: Future> FusedStream for FuturesUnordered<Fut> {
|
||||
fn is_terminated(&self) -> bool {
|
||||
self.is_terminated.load(Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut> Extend<Fut> for FuturesUnordered<Fut> {
|
||||
fn extend<I>(&mut self, iter: I)
|
||||
where
|
||||
I: IntoIterator<Item = Fut>,
|
||||
{
|
||||
for item in iter {
|
||||
self.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user