5 releases

0.2.3 Sep 3, 2024
0.2.2 Feb 8, 2024
0.2.1 Feb 8, 2024
0.2.0 Feb 8, 2024
0.1.0 Feb 8, 2024

#404 in Asynchronous

MIT/Apache

7KB

bisync

Easily write synchronous and asynchronous code at the same time.

This crate is inspired by maybe-async, but uses a different approach and tries to be more minimalistic.

How do I use it?

Annotate the functions you'd like to have generic w.r.t. asynchronisity with #[bisync]. You can specialize functions by annotating them with #[only_sync] or #[only_async].

You need a tiny bit of boilerplate in the parent module but that's all there is to it.

Example

// lib.rs

#[path = "."]
pub mod asynchronous {
    use bisync::asynchronous::*;
    mod inner;
    pub use inner::*;
}

// here you could also add `#[cfg]` attributes to enable or disable this module
#[path = "."]
pub mod blocking {
    use bisync::synchronous::*;
    mod inner;
    pub use inner::*;
}
// inner.rs

// these are all the available definitions:
use super::{bisync, only_sync, only_async, SYNC, ASYNC};
 
#[bisync]
pub async fn foo() -> String {
    bar().await
}
 
#[bisync]
async fn bar() -> String {
    if ASYNC {
        println!("We are in async code.");
    } else if SYNC {
        println!("We are in blocking code.");
    } else {
        panic!("This is neither async nor blocking code but a secret third thing.");
    }
 
    baz().await
}
 
#[only_sync]
fn baz() -> String {
    ureq::get("https://example.com")
        .call()
        .unwrap()
        .into_string()
        .unwrap()
}
 
#[only_async]
async fn baz() -> String {
    reqwest::get("https://example.com")
        .await
        .unwrap()
        .text()
        .await
        .unwrap()
}

The example above will strip away all async and await from the functions in the blocking module, but will leave them in the asynchronous module. Hence, you can easily use the functions either in a synchronous or an asynchronous context.

Dependencies