forked from mirror/async-std
Added Future::flatten
This commit is contained in:
parent
4c63392a85
commit
e0910be8fb
2 changed files with 73 additions and 0 deletions
|
@ -1,9 +1,12 @@
|
|||
cfg_unstable! {
|
||||
mod delay;
|
||||
mod flatten;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use delay::DelayFuture;
|
||||
use flatten::FlattenFuture;
|
||||
use crate::future::IntoFuture;
|
||||
}
|
||||
|
||||
extension_trait! {
|
||||
|
@ -129,6 +132,30 @@ extension_trait! {
|
|||
{
|
||||
DelayFuture::new(self, dur)
|
||||
}
|
||||
|
||||
/// Flatten out the execution of this future when the result itself
|
||||
/// can be converted into another future.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # async_std::task::block_on(async {
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let nested_future = async { async { 1 } };
|
||||
/// let future = nested_future.flatten();
|
||||
/// assert_eq!(future.await, 1);
|
||||
/// # })
|
||||
/// ```
|
||||
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
|
||||
#[cfg(any(feature = "unstable", feature = "docs"))]
|
||||
fn flatten(self) -> FlattenFuture<Self, <Self::Output as IntoFuture>::Future>
|
||||
where
|
||||
Self: Future + Sized,
|
||||
Self::Output: IntoFuture
|
||||
{
|
||||
FlattenFuture::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Future + Unpin + ?Sized> Future for Box<F> {
|
||||
|
|
46
src/future/future/flatten.rs
Normal file
46
src/future/future/flatten.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use futures_core::ready;
|
||||
use std::pin::Pin;
|
||||
|
||||
use crate::future::Future;
|
||||
use crate::future::IntoFuture;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug)]
|
||||
pub enum FlattenFuture<Fut1, Fut2> {
|
||||
First(Fut1),
|
||||
Second(Fut2),
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl<Fut1, Fut2> FlattenFuture<Fut1, Fut2> {
|
||||
pub fn new(future: Fut1) -> FlattenFuture<Fut1, Fut2> {
|
||||
FlattenFuture::First(future)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Fut1> Future for FlattenFuture<Fut1, <Fut1::Output as IntoFuture>::Future>
|
||||
where
|
||||
Fut1: Future,
|
||||
Fut1::Output: IntoFuture,
|
||||
{
|
||||
type Output = <Fut1::Output as IntoFuture>::Output;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = unsafe { self.get_unchecked_mut() };
|
||||
loop {
|
||||
match this {
|
||||
FlattenFuture::First(fut1) => {
|
||||
let fut2 = ready!(unsafe { Pin::new_unchecked(fut1) }.poll(cx)).into_future();
|
||||
*this = FlattenFuture::Second(fut2);
|
||||
}
|
||||
FlattenFuture::Second(fut2) => {
|
||||
let v = ready!(unsafe { Pin::new_unchecked(fut2) }.poll(cx));
|
||||
*this = FlattenFuture::Empty;
|
||||
return Poll::Ready(v);
|
||||
}
|
||||
FlattenFuture::Empty => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue