1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! # futures-utils-wasm
//!
//! A very simple crate for future-related utilities to abstract the differences between wasm and
//! non-wasm futures, namely the `Send` bound.

#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
use core::{future::Future, pin::Pin};

/// Macro that return an `impl Future` type, with a `Send` bound on non-wasm targets.
///
/// # Examples
///
/// ```
/// fn my_async_fn() -> futures_utils_wasm::impl_future!(<Output = ()>) {
///     async {}
/// }
/// ```
#[cfg(not(target_arch = "wasm32"))]
#[macro_export]
macro_rules! impl_future {
    (<$($t:tt)+) => {
        impl Send + $crate::private::Future<$($t)+
    };
}

/// Macro that return an `impl Future` type, with a `Send` bound on non-wasm targets.
///
/// # Examples
///
/// ```
/// fn my_async_fn() -> futures_utils_wasm::impl_future!(<Output = ()>) {
///     async {}
/// }
/// ```
#[cfg(target_arch = "wasm32")]
#[macro_export]
macro_rules! impl_future {
    (<$($t:tt)+) => {
        impl $crate::private::Future<$($t)+
    };
}

/// Type alias for a pin-boxed future, with a `Send` bound on non-wasm targets.
#[cfg(all(feature = "alloc", not(target_arch = "wasm32")))]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;

/// Type alias for a pin-boxed future, with a `Send` bound on non-wasm targets.
#[cfg(all(feature = "alloc", target_arch = "wasm32"))]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;

// Not public API.
#[doc(hidden)]
pub mod private {
    pub use core::future::Future;
}

#[cfg(test)]
mod tests {
    #[allow(unused_imports)]
    use super::*;

    fn _assert_future<T, F: Future<Output = T>>(_: F) {}

    fn _test_impl_future() {
        fn my_fn() -> impl_future!(<Output = ()>) {
            async {}
        }
        async fn my_async_fn() {}
        _assert_future(my_fn());
        _assert_future(my_async_fn());

        #[cfg(feature = "alloc")]
        {
            fn foo() -> BoxFuture<'static, ()> {
                Box::pin(async {})
            }
            _assert_future(foo());
        }
    }

    fn _test_impl_future_in_trait() {
        trait MyTrait {
            fn my_fn() -> impl_future!(<Output = ()>);
        }
        impl MyTrait for () {
            fn my_fn() -> impl_future!(<Output = ()>) {
                async {}
            }
        }
        impl MyTrait for u8 {
            async fn my_fn() {}
        }
        _assert_future(<()>::my_fn());
        _assert_future(<u8>::my_fn());
    }
}