1use std::sync::Mutex;
5use std::time::Instant;
6
7pub trait Clock: Send + Sync {
12 fn monotonic(&self) -> f64;
14
15 fn sleep(&self, seconds: f64);
17
18 #[cfg(feature = "tokio")]
21 fn sleep_async<'a>(
22 &'a self,
23 seconds: f64,
24 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send + 'a>>;
25}
26
27#[derive(Debug)]
29pub struct SystemClock {
30 start: Instant,
31}
32
33impl SystemClock {
34 pub fn new() -> Self {
36 Self {
37 start: Instant::now(),
38 }
39 }
40}
41
42impl Default for SystemClock {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
48impl Clock for SystemClock {
49 fn monotonic(&self) -> f64 {
50 self.start.elapsed().as_secs_f64()
51 }
52
53 fn sleep(&self, seconds: f64) {
54 if seconds > 0.0 {
55 std::thread::sleep(std::time::Duration::from_secs_f64(seconds));
56 }
57 }
58
59 #[cfg(feature = "tokio")]
60 fn sleep_async<'a>(
61 &'a self,
62 seconds: f64,
63 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send + 'a>> {
64 Box::pin(async move {
65 if seconds > 0.0 {
66 tokio::time::sleep(std::time::Duration::from_secs_f64(seconds)).await;
67 }
68 })
69 }
70}
71
72#[derive(Debug)]
75pub struct ManualClock {
76 now: Mutex<f64>,
77}
78
79impl ManualClock {
80 pub fn new(start: f64) -> Self {
82 Self {
83 now: Mutex::new(start),
84 }
85 }
86
87 pub fn advance(&self, seconds: f64) {
89 *self.now.lock().unwrap() += seconds;
90 }
91}
92
93impl Clock for ManualClock {
94 fn monotonic(&self) -> f64 {
95 *self.now.lock().unwrap()
96 }
97
98 fn sleep(&self, seconds: f64) {
99 self.advance(seconds);
100 }
101
102 #[cfg(feature = "tokio")]
103 fn sleep_async<'a>(
104 &'a self,
105 seconds: f64,
106 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send + 'a>> {
107 self.advance(seconds);
108 Box::pin(async {})
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn system_clock_advances_and_sleeps() {
119 let c = SystemClock::new();
120 let t0 = c.monotonic();
121 assert!(t0 >= 0.0);
122 c.sleep(0.0); c.sleep(-1.0); c.sleep(0.01);
125 assert!(c.monotonic() >= t0);
126 let _ = SystemClock::default();
128 assert!(format!("{c:?}").contains("SystemClock"));
129 }
130
131 #[test]
132 fn manual_clock_is_controllable() {
133 let c = ManualClock::new(1000.0);
134 assert_eq!(c.monotonic(), 1000.0);
135 c.advance(5.0);
136 assert_eq!(c.monotonic(), 1005.0);
137 c.sleep(2.5);
138 assert_eq!(c.monotonic(), 1007.5);
139 assert!(format!("{c:?}").contains("ManualClock"));
140 }
141
142 #[cfg(feature = "tokio")]
143 #[tokio::test]
144 async fn sleep_async_system_and_manual() {
145 let s = SystemClock::new();
146 s.sleep_async(0.0).await; s.sleep_async(0.01).await; let m = ManualClock::new(0.0);
149 m.sleep_async(5.0).await; assert_eq!(m.monotonic(), 5.0);
151 }
152}