Remit

Rust generators implemented through async/await syntax.
The pinned implementation is stack-based, and the boxed is heap-based.
No fancy macros and a simple API. Values can be lazily or eagerly yielded.
No dependencies outside of std.
Usage
Add to dependencies:
[dependencies]
remit = "0.1.1"
Example code:
use std::pin::pin;
use remit::{Generator, Remit};
async fn gen(remit: Remit<'_, usize>) {
remit.value(42).await;
for i in 1.. {
remit.value(i).await
}
}
for item in pin!(Generator::new()).of(gen).take(10) {
println!("{item}");
}
assert_eq!(vec![42, 1, 2, 3], pin!(Generator::new()).of(gen).take(4).collect::<Vec<_>>());
assert_eq!(vec![42, 1], Generator::boxed(gen).take(2).collect::<Vec<_>>());
assert_eq!(vec![1], Generator::boxed(|remit| async move { remit.value(1).await; }).collect::<Vec<_>>());
fn iter() -> impl Iterator<Item=usize> {
Generator::boxed(gen)
}
async fn scream<D: std::fmt::Display>(iter: impl Iterator<Item=D>, remit: Remit<'_, String>) {
for person in iter {
remit.value(format!("{person} scream!")).await
}
remit.value("... for ice cream!".to_string());
}
let expected: Vec<String> = ["You scream!", "I scream!", "We all scream!", "... for ice cream!"].iter().map(ToString::to_string).collect();
assert_eq!(
expected,
pin!(Generator::new()).parameterized(scream, ["You", "I", "We all"].iter()).collect::<Vec<String>>(),
);
assert_eq!(
expected,
Generator::boxed(|remit| scream(["You", "I", "We all"].iter(), remit)).collect::<Vec<String>>(),
);
License
MIT or APACHE-2, at your option.
See respective LICENSE files.