1use std::time::Duration;
2
3#[cfg(not(target_os = "emscripten"))]
5pub async fn timer(duration: Duration) {
6 async_io::Timer::after(duration).await;
7}
8
9#[cfg(target_os = "emscripten")]
11pub async fn timer(duration: Duration) {
12 use std::ffi::c_void;
13
14 use futures_channel::oneshot::{
15 Sender,
16 channel,
17 };
18
19 unsafe extern "C" {
20 fn emscripten_async_call(
21 callback: extern "C" fn(*mut c_void),
22 argument: *mut c_void,
23 millis: i32,
24 );
25 }
26
27 extern "C" fn wake(argument: *mut c_void) {
28 let sender = unsafe { Box::from_raw(argument.cast::<Sender<()>>()) };
29 sender.send(()).ok();
30 }
31
32 let (sender, receiver) = channel::<()>();
33 let argument = Box::into_raw(Box::new(sender)).cast();
34 let millis = duration.as_millis().min(i32::MAX as u128) as i32;
35
36 unsafe { emscripten_async_call(wake, argument, millis) };
37
38 receiver.await.ok();
39}