1use std::future::Future;
2use std::pin::Pin;
3
4use tokio::task::JoinHandle;
5
6#[cfg(feature = "native-runtime")]
7pub type RuntimeBoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
8
9#[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
10pub type RuntimeBoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
11
12#[cfg(feature = "wasm-runtime")]
13pub type RuntimeBoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
14
15#[cfg(feature = "native-runtime")]
16pub trait RuntimeFuture: Future + Send + 'static {}
17
18#[cfg(feature = "native-runtime")]
19impl<F> RuntimeFuture for F where F: Future + Send + 'static {}
20
21#[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
22pub trait RuntimeFuture: Future + Send + 'static {}
23
24#[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
25impl<F> RuntimeFuture for F where F: Future + Send + 'static {}
26
27#[cfg(feature = "wasm-runtime")]
28pub trait RuntimeFuture: Future + 'static {}
29
30#[cfg(feature = "wasm-runtime")]
31impl<F> RuntimeFuture for F where F: Future + 'static {}
32
33#[cfg(feature = "native-runtime")]
34pub trait RuntimeFutureOutput: Send + 'static {}
35
36#[cfg(feature = "native-runtime")]
37impl<T> RuntimeFutureOutput for T where T: Send + 'static {}
38
39#[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
40pub trait RuntimeFutureOutput: Send + 'static {}
41
42#[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
43impl<T> RuntimeFutureOutput for T where T: Send + 'static {}
44
45#[cfg(feature = "wasm-runtime")]
46pub trait RuntimeFutureOutput: 'static {}
47
48#[cfg(feature = "wasm-runtime")]
49impl<T> RuntimeFutureOutput for T where T: 'static {}
50
51#[derive(Clone, Copy, Debug, Default)]
52pub struct RuntimeSpawner;
53
54impl RuntimeSpawner {
55 #[cfg(feature = "native-runtime")]
56 pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
57 where
58 F: RuntimeFuture,
59 F::Output: RuntimeFutureOutput,
60 {
61 tokio::spawn(future)
62 }
63
64 #[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
65 pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
66 where
67 F: RuntimeFuture,
68 F::Output: RuntimeFutureOutput,
69 {
70 tokio::spawn(future)
71 }
72
73 #[cfg(feature = "wasm-runtime")]
74 pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
75 where
76 F: RuntimeFuture,
77 F::Output: RuntimeFutureOutput,
78 {
79 tokio::task::spawn_local(future)
80 }
81}
82
83#[cfg(feature = "native-runtime")]
84pub fn boxed_runtime_future<F, T>(future: F) -> RuntimeBoxFuture<T>
85where
86 F: Future<Output = T> + Send + 'static,
87{
88 Box::pin(future)
89}
90
91#[cfg(not(any(feature = "native-runtime", feature = "wasm-runtime")))]
92pub fn boxed_runtime_future<F, T>(future: F) -> RuntimeBoxFuture<T>
93where
94 F: Future<Output = T> + Send + 'static,
95{
96 Box::pin(future)
97}
98
99#[cfg(feature = "wasm-runtime")]
100pub fn boxed_runtime_future<F, T>(future: F) -> RuntimeBoxFuture<T>
101where
102 F: Future<Output = T> + 'static,
103{
104 Box::pin(future)
105}
106
107#[cfg(all(test, feature = "wasm-runtime"))]
108mod tests {
109 use std::cell::RefCell;
110 use std::rc::Rc;
111
112 use super::{RuntimeBoxFuture, boxed_runtime_future};
113
114 fn accepts_wasm_local_callback(
115 callback: impl Fn() -> RuntimeBoxFuture<()> + 'static,
116 ) -> impl Fn() -> RuntimeBoxFuture<()> {
117 callback
118 }
119
120 #[test]
121 fn wasm_runtime_box_future_accepts_local_callbacks() {
122 let state = Rc::new(RefCell::new(0));
123 let callback = accepts_wasm_local_callback({
124 let state = state.clone();
125 move || {
126 let state = state.clone();
127 boxed_runtime_future(async move {
128 *state.borrow_mut() += 1;
129 })
130 }
131 });
132
133 let _future = callback();
134 }
135}