futures_utils_wasm/
lib.rs

1//! # futures-utils-wasm
2//!
3//! A very simple crate for future-related utilities to abstract the differences between wasm and
4//! non-wasm futures, namely the `Send` bound.
5
6#![cfg_attr(docsrs, feature(doc_cfg))]
7#![cfg_attr(not(feature = "std"), no_std)]
8
9#[cfg(feature = "alloc")]
10extern crate alloc;
11
12#[cfg(all(feature = "alloc", not(feature = "std")))]
13use alloc::boxed::Box;
14use core::{future::Future, pin::Pin};
15
16/// Macro that return an `impl Future` type, with a `Send` bound on non-wasm targets.
17///
18/// # Examples
19///
20/// ```
21/// fn my_async_fn() -> futures_utils_wasm::impl_future!(<Output = ()>) {
22///     async {}
23/// }
24/// ```
25#[cfg(not(target_arch = "wasm32"))]
26#[macro_export]
27macro_rules! impl_future {
28    (<$($t:tt)+) => {
29        impl Send + $crate::private::Future<$($t)+
30    };
31}
32
33/// Macro that return an `impl Future` type, with a `Send` bound on non-wasm targets.
34///
35/// # Examples
36///
37/// ```
38/// fn my_async_fn() -> futures_utils_wasm::impl_future!(<Output = ()>) {
39///     async {}
40/// }
41/// ```
42#[cfg(target_arch = "wasm32")]
43#[macro_export]
44macro_rules! impl_future {
45    (<$($t:tt)+) => {
46        impl $crate::private::Future<$($t)+
47    };
48}
49
50/// Type alias for a pin-boxed future, with a `Send` bound on non-wasm targets.
51#[cfg(all(feature = "alloc", not(target_arch = "wasm32")))]
52#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
53pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;
54
55/// Type alias for a pin-boxed future, with a `Send` bound on non-wasm targets.
56#[cfg(all(feature = "alloc", target_arch = "wasm32"))]
57#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
58pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
59
60// Not public API.
61#[doc(hidden)]
62pub mod private {
63    pub use core::future::Future;
64}
65
66#[cfg(test)]
67mod tests {
68    #[allow(unused_imports)]
69    use super::*;
70
71    fn _assert_future<T, F: Future<Output = T>>(_: F) {}
72
73    fn _test_impl_future() {
74        fn my_fn() -> impl_future!(<Output = ()>) {
75            async {}
76        }
77        async fn my_async_fn() {}
78        _assert_future(my_fn());
79        _assert_future(my_async_fn());
80
81        #[cfg(feature = "alloc")]
82        {
83            fn foo() -> BoxFuture<'static, ()> {
84                Box::pin(async {})
85            }
86            _assert_future(foo());
87        }
88    }
89
90    fn _test_impl_future_in_trait() {
91        trait MyTrait {
92            fn my_fn() -> impl_future!(<Output = ()>);
93        }
94        impl MyTrait for () {
95            fn my_fn() -> impl_future!(<Output = ()>) {
96                async {}
97            }
98        }
99        impl MyTrait for u8 {
100            async fn my_fn() {}
101        }
102        _assert_future(<()>::my_fn());
103        _assert_future(<u8>::my_fn());
104    }
105}