susync 0.2.0

An util crate to complete futures through a handle. Its main purpose is to bridge async Rust and callback-based APIs.
Documentation
use susync::sus;
use susync::SuspendFuture;

// ********************** HELPER FUNCTIONS **********************
// **************************************************************

fn test_fn_empty(_a: i32, func: impl FnOnce()) {
    func();
}

fn test_multiple(a: i32, func: impl FnOnce(i32, f32)) {
    func(a, 69.0);
}

fn test_return(a: i32, func: impl FnOnce(i32) -> i32) {
    assert_eq!(func(a), a);
}

fn test_multiple_closures(a: impl FnOnce(i32, i32), b: impl FnOnce(i32)) {
    a(42, 69);
    b(42);
}

fn test_closure_with_str(func: impl FnOnce(i32, &str)) {
    func(42, "test");
}

#[derive(Clone, Debug)]
struct RefArgMock {
    member: i32,
}

fn test_ref(a: i32, func: impl FnOnce(i32, &RefArgMock)) -> i32 {
    func(a, &RefArgMock { member: a });
    a
}

fn test_single_ref(a: i32, func: impl FnOnce(&RefArgMock)) -> i32 {
    func(&RefArgMock { member: a });
    a
}

// **************************** TESTS ***************************
// **************************************************************

#[tokio::test]
async fn macro_empty_args() {
    let fut: SuspendFuture<()> = sus!(test_fn_empty(42, || { println!() }));
    fut.await.expect("result must be Ok");
}

#[tokio::test]
async fn macro_multiple_args() {
    let fut: SuspendFuture<(i32, f32)> = sus!(test_multiple(42, |integer, float| {
        println!("args: ({}, {})", integer, float);
    }));

    let res = fut.await.expect("result must be Ok");
    assert_eq!(res, (42, 69.0));
}

#[tokio::test]
async fn macro_name_collision() {
    let _fut: SuspendFuture<(i32, f32)> = sus!(test_multiple(42, |handle, float| {
        println!("args: ({}, {})", handle, float);
    }));
}

#[tokio::test]
async fn macro_ignore_arg() {
    let fut: SuspendFuture<i32> = sus!(test_multiple(42, |integer, _| {
        println!("args: ({}, _)", integer);
    }));
    let res = fut.await.expect("result must be OK");
    assert_eq!(res, 42);
}

#[tokio::test]
async fn macro_ignore_all_args() {
    let fut = sus!(test_multiple(42, |_, _| {
        println!("args: (_, _)");
    }));
    fut.await.expect("result must be OK");
}

#[tokio::test]
async fn macro_assert_return() {
    let fut: SuspendFuture<i32> = sus!(test_return(42, |integer| {
        println!("args: {}", integer);
        integer
    }));
    let res = fut.await.expect("result must be OK");
    assert_eq!(res, 42);
}

#[tokio::test]
async fn macro_closure_no_braces() {
    let fut = sus!(test_return(42, |x| x));
    let res = fut.await.expect("result must be OK");
    assert_eq!(res, 42);
}

#[tokio::test]
async fn macro_closure_no_body() {
    let fut = sus!(test_multiple(42, |a, b| {}));
    let res = fut.await.expect("result must be OK");
    assert_eq!(res, (42, 69.0));
}

#[tokio::test]
async fn macro_move_closure() {
    let fut = sus!(test_multiple(42, move |_, _| {
        println!("args: (_, _)");
    }));
    fut.await.expect("result must be OK");
}

#[tokio::test]
async fn macro_last_closure() {
    let fut = sus!(test_multiple_closures(
        |_a, _b| {},
        |x| {
            println!("args: {x}");
        }
    ));
    let res = fut.await.expect("result must be Ok");
    assert_eq!(res, 42);
}

#[tokio::test]
async fn macro_str_arg() {
    let fut = sus!(test_closure_with_str(|a, b| {
        println!("args: ({a}, {b})");
    }));
    let res = fut.await.expect("result must be Ok");
    assert_eq!(res, (42, "test".to_owned()));
}

#[tokio::test]
async fn macro_ref_args() {
    let fut = sus!(test_ref(42, |integer, reference| {
        println!("args: ({}, {:?})", integer, reference);
    }));
    let (integer, reference) = fut.await.expect("result must be OK");
    assert_eq!(integer, 42);
    assert_eq!(reference.member, 42);
}

#[tokio::test]
async fn macro_ref_single_arg() {
    let fut = sus!(test_single_ref(42, |reference| {
        println!("args: {:?}", reference);
    }));
    let reference = fut.await.expect("result must be OK");
    assert_eq!(reference.member, 42);
}