[−][src]Module genawaiter::rc
This module implements a generator which stores its state on the heap.
You can create a generator with Gen::new
. Pass it a
function that bootstraps the generator:
async fn producer(co: Co<i32>) { /* ... */ } let mut generator = Gen::new(producer);
See the crate-level docs for a guide on how to use the generator after it's been created.
Remarks
Do not let the Co
object escape the scope of the generator. Once the starting future
returns Poll::Ready
, the Co
object should already have been dropped. If this
invariant is not upheld, the result will be memory-safe but otherwise left unspecified.
Examples
Using Iterator
Generators implement Iterator
, so you can use them in a for loop:
for n in Gen::new(odd_numbers_less_than_ten) { println!("{}", n); }
Collecting into a Vec
let gen = Gen::new(odd_numbers_less_than_ten); let xs: Vec<_> = gen.into_iter().collect(); assert_eq!(xs, [1, 3, 5, 7, 9]);
Using resume()
let mut gen = Gen::new(odd_numbers_less_than_ten); assert_eq!(gen.resume(), GeneratorState::Yielded(1)); assert_eq!(gen.resume(), GeneratorState::Yielded(3)); assert_eq!(gen.resume(), GeneratorState::Yielded(5)); assert_eq!(gen.resume(), GeneratorState::Yielded(7)); assert_eq!(gen.resume(), GeneratorState::Yielded(9)); assert_eq!(gen.resume(), GeneratorState::Complete(()));
Using an async closure (nightly Rust only)
let mut gen = Gen::new(async move |co| { co.yield_(10).await; co.yield_(20).await; }); assert_eq!(gen.resume(), GeneratorState::Yielded(10)); assert_eq!(gen.resume(), GeneratorState::Yielded(20)); assert_eq!(gen.resume(), GeneratorState::Complete(()));
Using an async closure faux·sure (works on stable Rust)
let mut gen = Gen::new(|co| async move { co.yield_(10).await; co.yield_(20).await; }); assert_eq!(gen.resume(), GeneratorState::Yielded(10)); assert_eq!(gen.resume(), GeneratorState::Yielded(20)); assert_eq!(gen.resume(), GeneratorState::Complete(()));
Passing ordinary arguments
This is just ordinary Rust, nothing special.
async fn multiples_of(num: i32, co: Co<i32>) { let mut cur = num; loop { co.yield_(cur).await; cur += num; } } let mut gen = Gen::new(|co| multiples_of(10, co)); assert_eq!(gen.resume(), GeneratorState::Yielded(10)); assert_eq!(gen.resume(), GeneratorState::Yielded(20)); assert_eq!(gen.resume(), GeneratorState::Yielded(30));
Passing resume arguments
You can pass values into the generator.
Note that the first resume argument will be lost. This is because at the time the first value is sent, there is no future being awaited inside the generator, so there is no place the value could go where the generator could observe it.
async fn check_numbers(co: Co<(), i32>) { let num = co.yield_(()).await; assert_eq!(num, 1); let num = co.yield_(()).await; assert_eq!(num, 2); } let mut gen = Gen::new(check_numbers); gen.resume_with(0); gen.resume_with(1); gen.resume_with(2);
Returning a completion value
You can return a completion value with a different type than the values that are yielded.
async fn numbers_then_string(co: Co<i32>) -> &'static str { co.yield_(10).await; co.yield_(20).await; "done!" } let mut gen = Gen::new(numbers_then_string); assert_eq!(gen.resume(), GeneratorState::Yielded(10)); assert_eq!(gen.resume(), GeneratorState::Yielded(20)); assert_eq!(gen.resume(), GeneratorState::Complete("done!"));
Structs
Co | This object lets you yield values from the generator by calling the |
Gen | This is a generator which stores its state on the heap. |