split-async

Crates.iosplit-async
lib.rssplit-async
version0.1.1
created_at2025-07-13 19:27:07.405007+00
updated_at2025-07-13 23:38:50.054596+00
descriptionA procedural macro to generate sync and async versions of a function
homepage
repositoryhttps://github.com/gorilskij/split-async
max_upload_size
id1750728
size62,279
Pietro Gorilskij (gorilskij)

documentation

https://docs.rs/split-async

README

split-async

Why bother writing similar code twice for blocking and async code?

MIT licensed

This is a modified version of the maybe-async crate by Guoli Lyu.

When implementing both sync and async versions of a function, the implementations tend to be very similar, with the exception of the async and .await keywords.

This crate allows you to write just the async implementation of your function, a blocking version is then generated automatically.

Features:

  • Split your function into a blocking and an async version
  • Within your function, use other split functions by choosing which version to use

Examples

Here, loop_body can be arbitrarily complex and does not need to be duplicated. It can call either sync_operation or async_operation as appropriate, which can have completely different functionality. The loop mechanics are different so we write them individually in two small wrapper functions sync_loop and async_loop which can be used dynamically at will.

fn sync_operation(x: usize) -> usize { ... }

async fn async_operation(x: usize) -> usize { ... }

#[split]
async fn loop_body(x: usize) -> usize {
    // arbitrarily complex async logic
    choose!(operation)(x)
}

fn sync_loop() -> Vec<usize> {
    (0..100)
        .map(|x| sync_loop_body(x))
        .collect()
}

async fn async_loop() -> Vec<usize> {
    futures::stream::iter(0..100)
        .map(|x| sync_loop_body(x))
        .collect()
}
Commit count: 0

cargo fmt