File tree 2 files changed +73
-0
lines changed
2 files changed +73
-0
lines changed Original file line number Diff line number Diff line change 1
1
cfg_unstable ! {
2
2
mod delay;
3
+ mod flatten;
3
4
4
5
use std:: time:: Duration ;
5
6
6
7
use delay:: DelayFuture ;
8
+ use flatten:: FlattenFuture ;
9
+ use crate :: future:: IntoFuture ;
7
10
}
8
11
9
12
extension_trait ! {
@@ -129,6 +132,30 @@ extension_trait! {
129
132
{
130
133
DelayFuture :: new( self , dur)
131
134
}
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
+ }
132
159
}
133
160
134
161
impl <F : Future + Unpin + ?Sized > Future for Box <F > {
Original file line number Diff line number Diff line change
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
+ }
You can’t perform that action at this time.
0 commit comments