@@ -5,6 +5,26 @@ use core::pin::Pin;
5
5
6
6
/// an iterator that holds an internal coroutine representing
7
7
/// the iteration state
8
+ ///
9
+ /// # Example
10
+ /// pin a self-referenced coroutine in heap, then use it as `Iterator`
11
+ /// ```
12
+ /// #![feature(coroutines)]
13
+ ///
14
+ /// use gen_iter::GenIter;
15
+ /// use std::boxed::Box;
16
+ ///
17
+ /// let arr = [1, 2];
18
+ /// let c = Box::pin(#[coroutine] static move || {
19
+ /// let arr = &arr;
20
+ /// for i in 0..arr.len() {
21
+ /// yield arr[i];
22
+ /// }
23
+ /// });
24
+ /// let mut g = GenIter(c);
25
+ ///
26
+ /// assert_eq!(g.collect::<Vec<i32>>(), [1, 2]);
27
+ /// ```
8
28
#[ derive( Copy , Clone , Debug ) ]
9
29
pub struct GenIter < T > ( pub T )
10
30
where
38
58
39
59
/// macro to simplify iterator - via - coroutine construction
40
60
///
61
+ /// - movable coroutine as `Iterator`
41
62
/// ```
42
63
/// #![feature(coroutines)]
43
64
///
@@ -48,10 +69,24 @@ where
48
69
/// yield 2;
49
70
/// });
50
71
///
51
- /// assert_eq!(g.next(), Some(1));
52
- /// assert_eq!(g.next(), Some(2));
53
- /// assert_eq!(g.next(), None);
72
+ /// assert_eq!(g.collect::<Vec<i32>>(), [1, 2]);
73
+ /// ```
74
+ ///
75
+ /// - immovable coroutine (self referenced) as `Iterator`
76
+ /// ```
77
+ /// #![feature(coroutines)]
78
+ ///
79
+ /// use gen_iter::gen_iter;
80
+ ///
81
+ /// let arr = [1, 2];
82
+ /// let mut g = gen_iter!(static move {
83
+ /// let arr = &arr;
84
+ /// for i in 0..arr.len() {
85
+ /// yield arr[i];
86
+ /// }
87
+ /// });
54
88
///
89
+ /// assert_eq!(g.collect::<Vec<i32>>(), [1, 2]);
55
90
/// ```
56
91
#[ macro_export]
57
92
macro_rules! gen_iter {
@@ -60,7 +95,14 @@ macro_rules! gen_iter {
60
95
} ;
61
96
( move $block: block) => {
62
97
$crate:: GenIter ( #[ coroutine] move || $block)
63
- }
98
+ } ;
99
+
100
+ ( static $block: block) => {
101
+ $crate:: GenIter { 0 : :: core:: pin:: pin!( #[ coroutine] static || $block) }
102
+ } ;
103
+ ( static move $block: block) => {
104
+ $crate:: GenIter { 0 : :: core:: pin:: pin!( #[ coroutine] static move || $block) }
105
+ } ;
64
106
}
65
107
66
108
@@ -106,4 +148,50 @@ mod tests {
106
148
assert_eq ! ( g. next( ) , Some ( 2 ) ) ;
107
149
assert_eq ! ( g. next( ) , None ) ;
108
150
}
151
+
152
+ #[ test]
153
+ fn self_ref_coroutine_in_stack ( ) {
154
+ let c = :: core:: pin:: pin!( #[ coroutine] static || {
155
+ let v1 = [ 1 , 2 ] ;
156
+ let v = & v1;
157
+ for i in 0 ..v. len( ) {
158
+ yield v[ i] ;
159
+ }
160
+ } ) ;
161
+ let mut g = GenIter ( c) ;
162
+
163
+ assert_eq ! ( g. next( ) , Some ( 1 ) ) ;
164
+ assert_eq ! ( g. next( ) , Some ( 2 ) ) ;
165
+ assert_eq ! ( g. next( ) , None ) ;
166
+ }
167
+
168
+ #[ test]
169
+ fn gen_iter_macro_static ( ) {
170
+ let mut g = gen_iter ! ( static {
171
+ let v1 = [ 1 , 2 ] ;
172
+ let v = & v1;
173
+ for i in 0 ..v. len( ) {
174
+ yield v[ i] ;
175
+ }
176
+ } ) ;
177
+
178
+ assert_eq ! ( g. next( ) , Some ( 1 ) ) ;
179
+ assert_eq ! ( g. next( ) , Some ( 2 ) ) ;
180
+ assert_eq ! ( g. next( ) , None ) ;
181
+ }
182
+
183
+ #[ test]
184
+ fn gen_iter_macro_static_move ( ) {
185
+ let v1 = [ 1 , 2 ] ;
186
+ let mut g = gen_iter ! ( static move {
187
+ let v = & v1;
188
+ for i in 0 ..v. len( ) {
189
+ yield v[ i] ;
190
+ }
191
+ } ) ;
192
+
193
+ assert_eq ! ( g. next( ) , Some ( 1 ) ) ;
194
+ assert_eq ! ( g. next( ) , Some ( 2 ) ) ;
195
+ assert_eq ! ( g. next( ) , None ) ;
196
+ }
109
197
}
0 commit comments