Post #928001
2026-04-02 15:21 UTC
Been experimenting with coroutines in Rust. I wish there was some syntactic sugar when calling a coroutine inside another coroutine to automatically yield, like how the ? operator automatically returns None/Err. I'm using a little macro_rule to clean it up since I'm doing it so much.
"""
fn parse_data_state(
token_buffer: TokenBuffer,
) -> impl Coroutine<(), Yield = (), Return = Result<Option<token::Token>, error::TokenizerError>> {
#[coroutine]
move || {
match run_to_completion!(xml_decl::parse_xml_decl(token_buffer.clone())) {
Ok(Some(token)) => return Ok(Some(token)),
_ => (),
};
...
}
"""
"""
#[macro_export]
macro_rules! run_to_completion {
($coro:expr) => {{
let complete;
loop {
match core::ops::Coroutine::resume(Pin::new(&mut $coro), ()) {
core::ops::CoroutineState::Yielded(y) => yield y,
core::ops::CoroutineState::Complete(result) => {
complete = result;
break;
}
}
}
complete
}};
}
"""
#rust #rustlang
Replies (1)
-
@chmod777@tilde.zone 2026-04-02 15:30
With this I can have my sync and async code use the same code path very easily all I have to do is support the entry points. I have one for an embassy-sync channel another for an embassy-sync pipe and a sync entry that takes a &[u8]. #embassy