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