Skip to main content

generator_light/
ext.rs

1use crate::core::hint::unreachable_unchecked;
2
3use crate::core::ptr::NonNull;
4
5use crate::core::marker::{PhantomData, PhantomPinned};
6
7use crate::core::convert::Infallible;
8
9use crate::core::pin::Pin;
10
11use crate::fn_trait::FnOnceOutput;
12use crate::{Generator, GeneratorState};
13
14pub struct Iter<G>(G);
15
16impl<G> Iterator for Iter<G>
17where
18    G: Generator<(), Return = ()> + Unpin,
19{
20    type Item = G::Yield;
21
22    fn next(&mut self) -> Option<Self::Item> {
23        loop {
24            match Pin::new(&mut self.0).resume(()) {
25                GeneratorState::Complete(_) => return None,
26                GeneratorState::Suspend => continue,
27                GeneratorState::Yield(val) => return Some(val),
28            }
29        }
30    }
31}
32
33pub fn from_iter<Item>(
34    iter: impl IntoIterator<Item = Item>,
35) -> impl Generator<Yield = Item, Return = ()> {
36    struct GenIter<I: Iterator>(I);
37    impl<I: Iterator> Generator for GenIter<I> {
38        type Return = ();
39        type Yield = I::Item;
40        fn resume(self: Pin<&mut Self>, _value: ()) -> GeneratorState<Self::Yield, Self::Return> {
41            // SAFETY: We are not moving out of the pinned field.
42            match unsafe { self.get_unchecked_mut() }.0.next() {
43                Some(val) => GeneratorState::Yield(val),
44                None => GeneratorState::Complete(()),
45            }
46        }
47    }
48    GenIter(iter.into_iter())
49}
50
51pub const fn from_fn<Resume, Yield, Return>(
52    f: impl FnMut(Resume) -> GeneratorState<Yield, Return>,
53) -> impl Generator<Resume, Yield = Yield, Return = Return> {
54    struct GenFn<F>(F);
55    impl<F, R, Y, Out> Generator<R> for GenFn<F>
56    where
57        F: FnMut(R) -> GeneratorState<Y, Out>,
58    {
59        type Return = Out;
60        type Yield = Y;
61        fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
62            // SAFETY: We are not moving out of the pinned field.
63            unsafe { self.get_unchecked_mut() }.0(value)
64        }
65    }
66    GenFn(f)
67}
68
69pub trait GeneratorIterator {
70    type Item;
71    type Iter: Iterator<Item = Self::Item>;
72    fn into_iter(self) -> Self::Iter;
73}
74
75impl<G> GeneratorIterator for G
76where
77    G: Generator<(), Return = ()> + Unpin,
78{
79    type Item = G::Yield;
80    type Iter = Iter<G>;
81    fn into_iter(self) -> Self::Iter {
82        Iter(self)
83    }
84}
85
86pub use either::Either;
87
88pub trait GeneratorExt<R>: Generator<R> {
89    fn receiving<F, U>(self, f: F) -> Receiving<Self, F>
90    where
91        Self: Sized,
92        F: FnMut(U) -> R,
93    {
94        Receiving { g: self, f }
95    }
96
97    fn compose<G: Generator<Self::Yield>>(self, then: G) -> Compose<Self, G>
98    where
99        Self: Sized,
100    {
101        Compose {
102            first: self,
103            second: then,
104        }
105    }
106
107    fn map_complete<U, F>(self, f: F) -> MapComplete<Self, F>
108    where
109        Self: Sized,
110        F: FnOnce(Self::Return) -> U,
111    {
112        MapComplete {
113            generator: self,
114            f: Some(f),
115        }
116    }
117
118    fn map_yield<U, F>(self, f: F) -> MapYield<Self, F>
119    where
120        Self: Sized,
121        F: FnMut(Self::Yield) -> U,
122    {
123        MapYield { generator: self, f }
124    }
125
126    fn and_then<G, F>(self, f: F) -> AndThen<Self, F, G>
127    where
128        Self: Sized,
129        G: Generator<R, Yield = Self::Yield>,
130        F: FnOnce(Self::Return) -> G,
131    {
132        AndThen::Before {
133            g: self,
134            f: Some(f),
135        }
136    }
137
138    fn flatten(self) -> Flatten<Self, Self::Yield>
139    where
140        Self: Sized,
141        Self::Yield: Generator<R, Return = ()>,
142    {
143        Flatten {
144            g: self,
145            current: None,
146        }
147    }
148}
149
150impl<G, R> GeneratorExt<R> for G where G: Generator<R> {}
151
152pub struct Compose<A, B> {
153    first: A,
154    second: B,
155}
156
157impl<A, B, R> Generator<R> for Compose<A, B>
158where
159    A: Generator<R>,
160    B: Generator<A::Yield>,
161{
162    type Return = Either<A::Return, B::Return>;
163    type Yield = B::Yield;
164
165    fn resume(mut self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
166        let first = unsafe { self.as_mut().map_unchecked_mut(|this| &mut this.first) };
167        let value = match first.resume(value) {
168            GeneratorState::Suspend => return GeneratorState::Suspend,
169            GeneratorState::Complete(x) => return GeneratorState::Complete(Either::Left(x)),
170            GeneratorState::Yield(value) => value,
171        };
172        let second = unsafe { self.map_unchecked_mut(|this| &mut this.second) };
173        second.resume(value).map_complete(Either::Right)
174    }
175}
176
177pub struct MapComplete<G, F> {
178    generator: G,
179    f: Option<F>,
180}
181
182pub struct MapYield<G, F> {
183    generator: G,
184    f: F,
185}
186
187impl<G, F, R, U> Generator<R> for MapComplete<G, F>
188where
189    G: Generator<R>,
190    F: FnOnce(G::Return) -> U,
191{
192    type Yield = G::Yield;
193    type Return = U;
194
195    fn resume(mut self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
196        let g = unsafe { self.as_mut().map_unchecked_mut(|this| &mut this.generator) };
197        g.resume(value)
198            .map_complete(|r| unsafe { self.get_unchecked_mut() }.f.take().unwrap()(r))
199    }
200}
201
202impl<G, F, R, U> Generator<R> for MapYield<G, F>
203where
204    G: Generator<R>,
205    F: FnMut(G::Yield) -> U,
206{
207    type Yield = U;
208    type Return = G::Return;
209
210    fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
211        // safety: we are not moving out from the reference
212        let this = unsafe { self.get_unchecked_mut() };
213        let g = unsafe { Pin::new_unchecked(&mut this.generator) };
214        g.resume(value).map_yield(&mut this.f)
215    }
216}
217
218pub enum AndThen<G1, F, G2> {
219    Before { g: G1, f: Option<F> },
220    After { g: G2 },
221}
222
223impl<G1, F, G2, R> Generator<R> for AndThen<G1, F, G2>
224where
225    G1: Generator<R>,
226    F: FnOnce(G1::Return) -> G2,
227    G2: Generator<R, Yield = G1::Yield>,
228{
229    type Yield = G1::Yield;
230    type Return = G2::Return;
231
232    fn resume(mut self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
233        let this = unsafe { self.as_mut().get_unchecked_mut() };
234
235        match this {
236            AndThen::Before { g, f } => match unsafe { Pin::new_unchecked(g) }.resume(value) {
237                GeneratorState::Complete(r) => {
238                    let f = f.take().unwrap();
239                    let g = f(r);
240                    *this = AndThen::After { g };
241                    GeneratorState::Suspend
242                }
243                GeneratorState::Yield(y) => GeneratorState::Yield(y),
244                GeneratorState::Suspend => GeneratorState::Suspend,
245            },
246            AndThen::After { g } => unsafe { Pin::new_unchecked(g) }.resume(value),
247        }
248    }
249}
250
251pub struct Flatten<G, C> {
252    g: G,
253    current: Option<C>,
254}
255
256impl<R, G, C> Generator<R> for Flatten<G, C>
257where
258    G: Generator<R, Yield = C>,
259    C: Generator<R, Return = ()>,
260{
261    type Yield = C::Yield;
262    type Return = G::Return;
263
264    fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
265        let this = unsafe { self.get_unchecked_mut() };
266
267        if let Some(current) = &mut this.current {
268            match unsafe { Pin::new_unchecked(current) }.resume(value) {
269                GeneratorState::Suspend => GeneratorState::Suspend,
270                GeneratorState::Complete(()) => {
271                    this.current = None;
272                    GeneratorState::Suspend
273                }
274                GeneratorState::Yield(y) => GeneratorState::Yield(y),
275            }
276        } else {
277            match unsafe { Pin::new_unchecked(&mut this.g) }.resume(value) {
278                GeneratorState::Complete(r) => GeneratorState::Complete(r),
279                GeneratorState::Yield(c) => {
280                    this.current = Some(c);
281                    GeneratorState::Suspend
282                }
283                GeneratorState::Suspend => GeneratorState::Suspend,
284            }
285        }
286    }
287}
288
289pub struct Once<Y>(Option<Y>);
290pub struct OnceWith<F>(Option<F>);
291
292pub struct CompleteWith<F, Y>(Option<F>, PhantomData<Y>);
293
294impl<Y> Generator for Once<Y> {
295    type Return = ();
296    type Yield = Y;
297    fn resume(self: Pin<&mut Self>, _value: ()) -> GeneratorState<Self::Yield, Self::Return> {
298        let this = unsafe { self.get_unchecked_mut() };
299        if let Some(y) = this.0.take() {
300            GeneratorState::Yield(y)
301        } else {
302            GeneratorState::Complete(())
303        }
304    }
305}
306
307impl<F, R, Y> Generator<R> for OnceWith<F>
308where
309    F: FnOnce(R) -> Y,
310{
311    type Return = ();
312    type Yield = Y;
313    fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
314        let this = unsafe { self.get_unchecked_mut() };
315        if let Some(f) = this.0.take() {
316            GeneratorState::Yield(f(value))
317        } else {
318            GeneratorState::Complete(())
319        }
320    }
321}
322
323impl<F, R, C, Y> Generator<R> for CompleteWith<F, Y>
324where
325    F: FnOnce(R) -> C,
326{
327    type Return = C;
328    type Yield = Y;
329    fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
330        let this = unsafe { self.get_unchecked_mut() };
331        let f = this.0.take().unwrap();
332        GeneratorState::Complete(f(value))
333    }
334}
335
336pub const fn identity<Y>() -> impl Generator<Y, Yield = Y, Return = Infallible> {
337    from_fn(GeneratorState::Yield)
338}
339
340pub const fn once<Y>(yielded: Y) -> impl Generator<Yield = Y, Return = ()> {
341    Once(Some(yielded))
342}
343pub const fn once_with<F, R, Y>(f: F) -> impl Generator<R, Yield = Y, Return = ()>
344where
345    F: FnOnce(R) -> Y,
346{
347    OnceWith(Some(f))
348}
349
350pub const fn complete_with<F, Y, R, C>(f: F) -> impl Generator<R, Yield = Y, Return = C>
351where
352    F: FnOnce(R) -> C,
353{
354    CompleteWith(Some(f), PhantomData)
355}
356
357pub struct Receiving<G, F> {
358    g: G,
359    f: F,
360}
361
362impl<R1, R2, G, F> Generator<R1> for Receiving<G, F>
363where
364    F: FnMut(R1) -> R2,
365    G: Generator<R2>,
366{
367    type Yield = G::Yield;
368    type Return = G::Return;
369
370    fn resume(self: Pin<&mut Self>, value: R1) -> GeneratorState<Self::Yield, Self::Return> {
371        let this = unsafe { self.get_unchecked_mut() };
372        let r2 = (this.f)(value);
373        unsafe { Pin::new_unchecked(&mut this.g) }.resume(r2)
374    }
375}
376
377enum Gen<F, G> {
378    Init(Option<F>),
379    Gen(G),
380}
381
382struct ContextGen<C, R, F>
383where
384    F: FnOnceOutput<NonNull<C>, Out: Generator<R>>,
385{
386    context: Option<C>,
387    g: Gen<F, <F as FnOnceOutput<NonNull<C>>>::Out>,
388    _pinned: PhantomPinned,
389    _resume: PhantomData<R>,
390}
391
392impl<C, R, F> Generator<R> for ContextGen<C, R, F>
393where
394    F: FnOnceOutput<NonNull<C>, Out: Generator<R, Return = ()>>,
395{
396    type Return = C;
397    type Yield = <<F as FnOnceOutput<NonNull<C>>>::Out as Generator<R>>::Yield;
398
399    fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
400        let this = unsafe { self.get_unchecked_mut() };
401        if let Gen::Init(f) = &mut this.g {
402            let g = f
403                .take()
404                .unwrap()
405                .call(NonNull::from_mut(this.context.as_mut().unwrap()));
406            this.g = Gen::Gen(g);
407        };
408        let Gen::Gen(g) = &mut this.g else {
409            unsafe { unreachable_unchecked() };
410        };
411        unsafe { Pin::new_unchecked(g) }
412            .resume(value)
413            .map_complete(|_| this.context.take().unwrap())
414    }
415}
416
417// Capture context C to the contextless function f
418pub const fn context<C, R, Yield>(
419    c: C,
420    f: impl for<'a> FnOnceOutput<&'a mut C, Out: Generator<R, Yield = Yield, Return = ()>>,
421) -> impl Generator<R, Yield = Yield, Return = C> {
422    ContextGen::<C, R, _> {
423        context: Some(c),
424        g: Gen::Init(Some(move |ptr: NonNull<C>| unsafe {
425            f.call(&mut *ptr.as_ptr())
426        })),
427        _pinned: PhantomPinned,
428        _resume: PhantomData,
429    }
430}