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
37 fn resume(mut self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
39 G::resume(Pin::new(&mut **self), value)
40 }
41}
42
43#[cfg(feature = "std")]
44impl<R, G> Generator<R> for core::boxed::Box<G>
45where
46 G: Generator<R> + ?Sized + Unpin,
47{
48 type Return = G::Return;
49 type Yield = G::Yield;
50
51 fn resume(mut self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
53 G::resume(Pin::new(&mut **self), value)
54 }
55}
56
57impl<R, P> Generator<R> for Pin<P>
58where
59 P: DerefMut<Target: Generator<R>>,
60{
61 type Return = <P::Target as Generator<R>>::Return;
62 type Yield = <P::Target as Generator<R>>::Yield;
63
64 fn resume(self: Pin<&mut Self>, value: R) -> GeneratorState<Self::Yield, Self::Return> {
65 <P::Target as Generator<R>>::resume(self.as_deref_mut(), value)
66 }
67}
68
69pub fn generator<F, Resume, Yield, Return>(
72 f: F,
73) -> impl Generator<Resume, Yield = Yield, Return = Return>
74where
75 for<'a> F: FnOnceOutput<Yielder<'a, Yield, Resume>, Out: Future<Output = Return>>,
78{
79 fut_generator::fut_generator(f)
80}
81
82#[cfg(test)]
83mod tests {
84
85 use crate::core::pin::pin;
86
87 use crate::{ext::GeneratorIterator, *};
88
89 fn squares(n: usize) -> impl Generator<Yield = usize, Return = ()> {
90 generator(async move |mut this: Yielder<_, _>| {
91 for x in 1..=n {
92 yield_!(this, x * x);
93 }
94 })
95 }
96
97 fn tok_generator<'a>(s: &'a str) -> impl Generator<Yield = &'a str, Return = ()> {
98 generator(async move |mut this: Yielder<_, _>| {
99 for tok in s.split_whitespace() {
100 yield_!(this, tok);
101 }
102 })
103 }
104
105 #[test]
106 fn test_squares() {
107 let g = pin!(squares(5));
108 let mut g = g.into_iter();
109 assert_eq!(g.next(), Some(1));
110 assert_eq!(g.next(), Some(4));
111 assert_eq!(g.next(), Some(9));
112 assert_eq!(g.next(), Some(16));
113 assert_eq!(g.next(), Some(25));
114 assert_eq!(g.next(), None);
115 }
116
117 #[test]
118 fn test_tokens() {
119 let g = pin!(tok_generator("hello world"));
120 let mut g = g.into_iter();
121 assert_eq!(g.next(), Some("hello"));
122 assert_eq!(g.next(), Some("world"));
123 assert_eq!(g.next(), None);
124 }
125}