-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtime.rs
103 lines (86 loc) · 2.69 KB
/
time.rs
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
use std::ffi::c_ulonglong;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use std::sync::OnceLock;
use std::time::{Duration, Instant};
use iced::Subscription;
use crate::future::RawFuture;
use crate::{free_haskell_fun_ptr, IcedMessage, Message};
static STARTED_AT: OnceLock<Instant> = OnceLock::new();
type OnEvery = extern "C" fn(micros: c_ulonglong) -> Message;
#[no_mangle]
extern "C" fn duration_from_secs(value: c_ulonglong) -> *mut Duration {
let duration = Duration::from_secs(value);
Box::into_raw(Box::new(duration))
}
#[no_mangle]
extern "C" fn duration_from_millis(value: c_ulonglong) -> *mut Duration {
let duration = Duration::from_millis(value);
Box::into_raw(Box::new(duration))
}
#[no_mangle]
extern "C" fn duration_from_micros(value: c_ulonglong) -> *mut Duration {
let duration = Duration::from_micros(value);
Box::into_raw(Box::new(duration))
}
#[no_mangle]
extern "C" fn duration_from_nanos(value: c_ulonglong) -> *mut Duration {
let duration = Duration::from_nanos(value);
Box::into_raw(Box::new(duration))
}
#[no_mangle]
extern "C" fn tokio_time_sleep(duration_ptr: *mut Duration) -> RawFuture<()> {
let duration = unsafe { *Box::from_raw(duration_ptr) };
let pinned = Box::pin(tokio::time::sleep(duration));
Box::into_raw(Box::new(pinned))
}
fn time_passed_micros(instant: Instant) -> u64 {
let start = STARTED_AT.get_or_init(Instant::now);
instant.duration_since(*start).as_micros() as u64
}
struct HaskellClosure {
on_every: OnEvery,
}
impl Drop for HaskellClosure {
fn drop(&mut self) {
unsafe { free_haskell_fun_ptr(self.on_every as usize) };
}
}
#[derive(Clone)]
struct Closure {
internal: Arc<HaskellClosure>,
}
impl Hash for Closure {
fn hash<H: Hasher>(&self, state: &mut H) {
"time_on_every".hash(state);
}
}
impl Closure {
fn new(on_every: OnEvery) -> Self {
let internal = Arc::new(HaskellClosure { on_every });
Closure { internal }
}
fn call(&self, micros: u64) -> IcedMessage {
let message_ptr = (self.internal.on_every)(micros);
IcedMessage::ptr(message_ptr)
}
}
#[no_mangle]
extern "C" fn iced_time_every(
duration_ptr: *mut Duration,
on_every: OnEvery,
) -> *mut Subscription<IcedMessage> {
let duration = unsafe { *Box::from_raw(duration_ptr) };
let on_every = Closure::new(on_every);
let every = iced::time::every(duration)
.with(on_every)
.map(|(on_every, instant)| {
let micros = time_passed_micros(instant);
on_every.call(micros)
});
Box::into_raw(Box::new(every))
}
#[no_mangle]
extern "C" fn time_micros_since_start() -> c_ulonglong {
time_passed_micros(Instant::now())
}