ruvector_mincut/
time_compat.rs1use std::sync::atomic::{AtomicU64, Ordering};
9
10#[cfg(feature = "wasm")]
12static MONOTONIC_COUNTER: AtomicU64 = AtomicU64::new(0);
13
14#[derive(Debug, Clone, Copy)]
16pub struct PortableInstant {
17 #[cfg(not(feature = "wasm"))]
18 inner: std::time::Instant,
19 #[cfg(feature = "wasm")]
20 counter: u64,
21}
22
23impl PortableInstant {
24 #[cfg(not(feature = "wasm"))]
26 pub fn now() -> Self {
27 Self {
28 inner: std::time::Instant::now(),
29 }
30 }
31
32 #[cfg(feature = "wasm")]
34 pub fn now() -> Self {
35 let counter = MONOTONIC_COUNTER.fetch_add(1, Ordering::SeqCst);
36 Self { counter }
37 }
38
39 #[cfg(not(feature = "wasm"))]
41 pub fn elapsed_micros(&self) -> u64 {
42 self.inner.elapsed().as_micros() as u64
43 }
44
45 #[cfg(feature = "wasm")]
47 pub fn elapsed_micros(&self) -> u64 {
48 let current = MONOTONIC_COUNTER.load(Ordering::SeqCst);
49 current.saturating_sub(self.counter)
52 }
53
54 #[cfg(not(feature = "wasm"))]
56 pub fn elapsed(&self) -> std::time::Duration {
57 self.inner.elapsed()
58 }
59
60 #[cfg(feature = "wasm")]
62 pub fn elapsed(&self) -> std::time::Duration {
63 std::time::Duration::from_micros(self.elapsed_micros())
64 }
65
66 #[cfg(not(feature = "wasm"))]
68 pub fn duration_since(&self, earlier: Self) -> std::time::Duration {
69 self.inner.duration_since(earlier.inner)
70 }
71
72 #[cfg(feature = "wasm")]
74 pub fn duration_since(&self, earlier: Self) -> std::time::Duration {
75 let diff = self.counter.saturating_sub(earlier.counter);
76 std::time::Duration::from_micros(diff)
77 }
78}
79
80impl Default for PortableInstant {
81 fn default() -> Self {
82 Self::now()
83 }
84}
85
86#[derive(Debug, Clone, Copy)]
88pub struct PortableTimestamp {
89 pub secs: u64,
91}
92
93impl PortableTimestamp {
94 #[cfg(not(feature = "wasm"))]
96 pub fn now() -> Self {
97 let secs = std::time::SystemTime::now()
98 .duration_since(std::time::UNIX_EPOCH)
99 .unwrap_or_default()
100 .as_secs();
101 Self { secs }
102 }
103
104 #[cfg(feature = "wasm")]
106 pub fn now() -> Self {
107 let secs = MONOTONIC_COUNTER.fetch_add(1, Ordering::SeqCst);
108 Self { secs }
109 }
110
111 pub fn as_secs(&self) -> u64 {
113 self.secs
114 }
115}
116
117impl Default for PortableTimestamp {
118 fn default() -> Self {
119 Self::now()
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_portable_instant() {
129 let start = PortableInstant::now();
130 let _sum: u64 = (0..1000).sum();
132 let elapsed = start.elapsed_micros();
133 #[cfg(not(feature = "wasm"))]
135 assert!(elapsed >= 0);
136 }
137
138 #[test]
139 fn test_portable_timestamp() {
140 let ts1 = PortableTimestamp::now();
141 let ts2 = PortableTimestamp::now();
142 assert!(ts2.secs >= ts1.secs);
144 }
145
146 #[test]
147 fn test_instant_ordering() {
148 let t1 = PortableInstant::now();
149 let t2 = PortableInstant::now();
150 let d = t2.duration_since(t1);
151 assert!(d.as_micros() >= 0);
153 }
154}