1use core::iter::{FusedIterator, Iterator};
2use core::marker::Unpin;
3use core::ops::{Coroutine, CoroutineState};
4use core::pin::Pin;
5
6#[derive(Copy, Clone, Debug)]
9pub struct GenIter<T>(pub T)
10where
11 T: Coroutine<Return = ()> + Unpin;
12
13impl<T> Iterator for GenIter<T>
14where
15 T: Coroutine<Return = ()> + Unpin,
16{
17 type Item = T::Yield;
18
19 #[inline]
20 fn next(&mut self) -> Option<Self::Item> {
21 match Pin::new(&mut self.0).resume(()) {
22 CoroutineState::Yielded(n) => Some(n),
23 CoroutineState::Complete(()) => None,
24 }
25 }
26}
27
28impl<G> From<G> for GenIter<G>
29where
30 G: Coroutine<Return = ()> + Unpin,
31{
32 #[inline]
33 fn from(gen: G) -> Self {
34 GenIter(gen)
35 }
36}
37
38#[macro_export]
56macro_rules! gen_iter {
57 ($block: block) => {
58 $crate::gen_iter::GenIter(
59 #[coroutine]
60 || $block,
61 )
62 };
63 (move $block: block) => {
64 $crate::gen_iter::GenIter(
65 #[coroutine]
66 move || $block,
67 )
68 };
69}
70
71#[derive(Copy, Clone, Debug)]
79pub struct GenIterReturn<G: Coroutine + Unpin>(Result<G::Return, G>);
80
81impl<G: Coroutine + Unpin> GenIterReturn<G> {
82 #[inline]
83 pub fn new(g: G) -> Self {
84 GenIterReturn(Err(g))
85 }
86
87 #[inline]
88 pub fn is_done(&self) -> bool {
89 self.0.is_ok()
90 }
91
92 #[inline]
93 pub fn return_or_self(self) -> Result<G::Return, Self> {
94 match self.0 {
95 Ok(r) => Ok(r),
96 Err(_) => Err(self),
97 }
98 }
99}
100
101impl<G: Coroutine + Unpin> Iterator for &mut GenIterReturn<G> {
112 type Item = G::Yield;
113
114 #[inline]
115 fn next(&mut self) -> Option<Self::Item> {
116 match self.0 {
117 Ok(_) => None,
118 Err(ref mut g) => match Pin::new(g).resume(()) {
119 CoroutineState::Yielded(y) => Some(y),
120 CoroutineState::Complete(r) => {
121 self.0 = Ok(r);
122 None
123 }
124 },
125 }
126 }
127}
128
129impl<G: Coroutine + Unpin> FusedIterator for &mut GenIterReturn<G> {}
131
132impl<G: Coroutine + Unpin> From<G> for GenIterReturn<G> {
133 #[inline]
134 fn from(g: G) -> Self {
135 GenIterReturn::new(g)
136 }
137}
138
139#[macro_export]
157macro_rules! gen_iter_return {
158 ($block: block) => {
159 $crate::gen_iter::GenIterReturn::new(
160 #[coroutine]
161 || $block,
162 )
163 };
164 (move $block: block) => {
165 $crate::gen_iter::GenIterReturn::new(
166 #[coroutine]
167 move || $block,
168 )
169 };
170}
171
172#[cfg(test)]
173mod tests {
174 use super::GenIterReturn;
175
176 #[test]
177 fn gen_iter_works() {
178 let mut g = gen_iter!({
179 yield 1;
180 yield 2;
181 });
182
183 assert_eq!(g.next(), Some(1));
184 assert_eq!(g.next(), Some(2));
185 assert_eq!(g.next(), None);
186 }
187
188 #[test]
189 fn gen_iter_macro() {
190 let mut g = gen_iter!(move {
191 yield 1;
192 yield 2;
193 });
194
195 assert_eq!(g.next(), Some(1));
196 assert_eq!(g.next(), Some(2));
197 assert_eq!(g.next(), None);
198 }
199
200 #[test]
203 fn gen_iter_return_works() {
204 let mut g = GenIterReturn::new(
205 #[coroutine]
206 || {
207 yield 1;
208 "done"
209 },
210 );
211
212 assert_eq!((&mut g).next(), Some(1));
213 assert!(!g.is_done());
214
215 g = match g.return_or_self() {
216 Ok(_) => panic!("coroutine is done but should not"),
217 Err(g) => g,
218 };
219
220 assert_eq!((&mut g).next(), None);
221 assert!(g.is_done());
222
223 assert_eq!((&mut g).next(), None); assert_eq!(g.return_or_self().ok(), Some("done"));
226 }
227
228 #[test]
229 fn from_coroutine() {
230 let mut g = GenIterReturn::from(
231 #[coroutine]
232 || {
233 yield 1;
234 "done"
235 },
236 );
237
238 assert_eq!((&mut g).next(), Some(1));
239 assert_eq!((&mut g).next(), None);
240
241 assert!(g.is_done());
242 assert_eq!(g.return_or_self().ok(), Some("done"));
243 }
244
245 #[test]
247 fn macro_usage() {
248 let mut g = gen_iter_return!(move {
249 yield 1;
250 yield 2;
251 return "done";
252 });
253
254 let (mut sum, mut count) = (0, 0);
255 for y in &mut g {
256 sum += y;
257 count += 1;
258 }
259 assert_eq!((sum, count), (3, 2));
260
261 assert!(g.is_done());
262 assert_eq!(g.return_or_self().ok(), Some("done"));
263 }
264}