Skip to content

Commit e0910be

Browse files
author
Abhishek C. Sharma
committed
Added Future::flatten
1 parent 4c63392 commit e0910be

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/future/future.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
cfg_unstable! {
22
mod delay;
3+
mod flatten;
34

45
use std::time::Duration;
56

67
use delay::DelayFuture;
8+
use flatten::FlattenFuture;
9+
use crate::future::IntoFuture;
710
}
811

912
extension_trait! {
@@ -129,6 +132,30 @@ extension_trait! {
129132
{
130133
DelayFuture::new(self, dur)
131134
}
135+
136+
/// Flatten out the execution of this future when the result itself
137+
/// can be converted into another future.
138+
///
139+
/// # Examples
140+
///
141+
/// ```
142+
/// # async_std::task::block_on(async {
143+
/// use async_std::prelude::*;
144+
///
145+
/// let nested_future = async { async { 1 } };
146+
/// let future = nested_future.flatten();
147+
/// assert_eq!(future.await, 1);
148+
/// # })
149+
/// ```
150+
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
151+
#[cfg(any(feature = "unstable", feature = "docs"))]
152+
fn flatten(self) -> FlattenFuture<Self, <Self::Output as IntoFuture>::Future>
153+
where
154+
Self: Future + Sized,
155+
Self::Output: IntoFuture
156+
{
157+
FlattenFuture::new(self)
158+
}
132159
}
133160

134161
impl<F: Future + Unpin + ?Sized> Future for Box<F> {

src/future/future/flatten.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use futures_core::ready;
2+
use std::pin::Pin;
3+
4+
use crate::future::Future;
5+
use crate::future::IntoFuture;
6+
use crate::task::{Context, Poll};
7+
8+
#[doc(hidden)]
9+
#[derive(Debug)]
10+
pub enum FlattenFuture<Fut1, Fut2> {
11+
First(Fut1),
12+
Second(Fut2),
13+
Empty,
14+
}
15+
16+
impl<Fut1, Fut2> FlattenFuture<Fut1, Fut2> {
17+
pub fn new(future: Fut1) -> FlattenFuture<Fut1, Fut2> {
18+
FlattenFuture::First(future)
19+
}
20+
}
21+
22+
impl<Fut1> Future for FlattenFuture<Fut1, <Fut1::Output as IntoFuture>::Future>
23+
where
24+
Fut1: Future,
25+
Fut1::Output: IntoFuture,
26+
{
27+
type Output = <Fut1::Output as IntoFuture>::Output;
28+
29+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
30+
let this = unsafe { self.get_unchecked_mut() };
31+
loop {
32+
match this {
33+
FlattenFuture::First(fut1) => {
34+
let fut2 = ready!(unsafe { Pin::new_unchecked(fut1) }.poll(cx)).into_future();
35+
*this = FlattenFuture::Second(fut2);
36+
}
37+
FlattenFuture::Second(fut2) => {
38+
let v = ready!(unsafe { Pin::new_unchecked(fut2) }.poll(cx));
39+
*this = FlattenFuture::Empty;
40+
return Poll::Ready(v);
41+
}
42+
FlattenFuture::Empty => unreachable!(),
43+
}
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)