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

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

@chmod777 I have to say...

The opposite of "async" is not "sync"

I write asynchronous real-time audio processing code, and I never use async