1#![no_std]
2
3mod fut_generator;
4
5pub(crate) mod fn_trait;
6pub(crate) mod gen_context;
7
8pub mod ext;
9pub mod generator_state;
10
11use core::{ops::DerefMut, pin::Pin};
12
13use crate::fn_trait::FnOnceOutput;
14pub use crate::gen_context::Yielder;
15pub use crate::generator_state::GeneratorState;
16
17pub trait Generator<R = ()> {
18 type Yield;
19 type Return;
20 fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return>;
21}
22
23impl<R, G> Generator<R> for &mut G
24where
25 G: Generator<R> + ?Sized + Unpin,
26{
27 type Return = G::Return;
28 type Yield = G::Yield;
29 fn resume(mut self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
30 G::resume(Pin::new(&mut **self), value)
31 }
32}
33
34impl<R, P> Generator<R> for Pin<P>
35where
36 P: DerefMut<Target: Generator<R>>,
37{
38 type Return = <P::Target as Generator<R>>::Return;
39 type Yield = <P::Target as Generator<R>>::Yield;
40
41 fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
42 <P::Target as Generator<R>>::resume(self.as_deref_mut(), value)
43 }
44}
45
46pub const fn generator<F, Resume, Yield, Return>(
51 f: F,
52) -> impl Generator<Resume, Yield = Yield, Return = Return>
53where
54 for<'a> F: FnOnceOutput<Yielder<'a, Yield, Resume>, Resume, Out: Future<Output = Return>>,
57{
58 fut_generator::Generator::new(f)
59}
60
61#[cfg(test)]
62mod tests {
63
64 use core::pin::pin;
65
66 use crate::{ext::GeneratorIterator, *};
67
68 fn squares(n: usize) -> impl Generator<Yield = usize, Return = ()> {
69 generator(async move |mut this: Yielder<_, _>, _| {
70 for x in 1..=n {
71 yield_!(this, x * x);
72 }
73 })
74 }
75
76 fn tok_generator<'a>(s: &'a str) -> impl Generator<Yield = &'a str, Return = ()> {
77 generator(async move |mut this: Yielder<_, _>, _| {
78 for tok in s.split_whitespace() {
79 yield_!(this, tok);
80 }
81 })
82 }
83
84 #[test]
85 fn test_squares() {
86 let g = pin!(squares(5));
87 let mut g = g.into_iter();
88 assert_eq!(g.next(), Some(1));
89 assert_eq!(g.next(), Some(4));
90 assert_eq!(g.next(), Some(9));
91 assert_eq!(g.next(), Some(16));
92 assert_eq!(g.next(), Some(25));
93 assert_eq!(g.next(), None);
94 }
95
96 #[test]
97 fn test_tokens() {
98 let g = pin!(tok_generator("hello world"));
99 let mut g = g.into_iter();
100 assert_eq!(g.next(), Some("hello"));
101 assert_eq!(g.next(), Some("world"));
102 assert_eq!(g.next(), None);
103 }
104}