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