Skip to main content

ruvector_sona/
time_compat.rs

1//! Cross-platform time abstraction for native and WASM targets.
2//!
3//! Uses `std::time::Instant` on native platforms and `performance.now()` on WASM.
4//! Uses `std::time::SystemTime` on native platforms and `Date.now()` on WASM.
5
6#[cfg(not(target_arch = "wasm32"))]
7mod native {
8    use std::fmt;
9    use std::time::{Duration, Instant as StdInstant, SystemTime as StdSystemTime, UNIX_EPOCH};
10
11    #[derive(Clone, Copy)]
12    pub struct Instant(StdInstant);
13
14    impl Instant {
15        pub fn now() -> Self {
16            Instant(StdInstant::now())
17        }
18
19        pub fn elapsed(&self) -> Duration {
20            self.0.elapsed()
21        }
22    }
23
24    impl Default for Instant {
25        fn default() -> Self {
26            Self::now()
27        }
28    }
29
30    impl fmt::Debug for Instant {
31        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32            self.0.fmt(f)
33        }
34    }
35
36    #[derive(Clone, Copy)]
37    pub struct SystemTime(StdSystemTime);
38
39    impl SystemTime {
40        pub fn now() -> Self {
41            SystemTime(StdSystemTime::now())
42        }
43
44        pub fn duration_since_epoch(&self) -> Duration {
45            self.0.duration_since(UNIX_EPOCH).unwrap_or(Duration::ZERO)
46        }
47    }
48
49    impl fmt::Debug for SystemTime {
50        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51            self.0.fmt(f)
52        }
53    }
54}
55
56#[cfg(target_arch = "wasm32")]
57mod wasm {
58    use std::fmt;
59    use std::time::Duration;
60
61    fn performance_now() -> f64 {
62        #[cfg(feature = "wasm")]
63        {
64            use wasm_bindgen::JsCast;
65            js_sys::Reflect::get(&js_sys::global(), &"performance".into())
66                .ok()
67                .and_then(|p| p.dyn_into::<web_sys::Performance>().ok())
68                .map(|p| p.now())
69                .unwrap_or(0.0)
70        }
71        #[cfg(not(feature = "wasm"))]
72        {
73            0.0
74        }
75    }
76
77    fn date_now() -> f64 {
78        #[cfg(feature = "wasm")]
79        {
80            js_sys::Date::now()
81        }
82        #[cfg(not(feature = "wasm"))]
83        {
84            0.0
85        }
86    }
87
88    #[derive(Clone, Copy)]
89    pub struct Instant(f64);
90
91    impl Instant {
92        pub fn now() -> Self {
93            Instant(performance_now())
94        }
95
96        pub fn elapsed(&self) -> Duration {
97            let now = performance_now();
98            let elapsed_ms = (now - self.0).max(0.0);
99            Duration::from_secs_f64(elapsed_ms / 1000.0)
100        }
101    }
102
103    impl Default for Instant {
104        fn default() -> Self {
105            Self::now()
106        }
107    }
108
109    impl fmt::Debug for Instant {
110        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111            write!(f, "Instant({}ms)", self.0)
112        }
113    }
114
115    #[derive(Clone, Copy)]
116    pub struct SystemTime(f64);
117
118    impl SystemTime {
119        pub fn now() -> Self {
120            SystemTime(date_now())
121        }
122
123        pub fn duration_since_epoch(&self) -> Duration {
124            Duration::from_secs_f64(self.0 / 1000.0)
125        }
126    }
127
128    impl fmt::Debug for SystemTime {
129        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130            write!(f, "SystemTime({}ms)", self.0)
131        }
132    }
133}
134
135#[cfg(not(target_arch = "wasm32"))]
136pub use native::{Instant, SystemTime};
137
138#[cfg(target_arch = "wasm32")]
139pub use wasm::{Instant, SystemTime};