clipper2_rust/utils/
timer.rs1use std::time::{Duration, Instant};
8
9pub struct Timer {
25 time_started: Instant,
26 duration: Duration,
27 paused: bool,
28}
29
30impl Timer {
31 pub fn new(start_paused: bool) -> Self {
33 Self {
34 time_started: Instant::now(),
35 duration: Duration::ZERO,
36 paused: start_paused,
37 }
38 }
39
40 pub fn restart(&mut self) {
42 self.paused = false;
43 self.duration = Duration::ZERO;
44 self.time_started = Instant::now();
45 }
46
47 pub fn resume(&mut self) {
49 if !self.paused {
50 return;
51 }
52 self.paused = false;
53 self.time_started = Instant::now();
54 }
55
56 pub fn pause(&mut self) {
58 if self.paused {
59 return;
60 }
61 self.duration += self.time_started.elapsed();
62 self.paused = true;
63 }
64
65 pub fn elapsed(&self) -> Duration {
70 if self.paused {
71 self.duration
72 } else {
73 self.duration + self.time_started.elapsed()
74 }
75 }
76
77 pub fn elapsed_nanos(&self) -> u128 {
80 self.elapsed().as_nanos()
81 }
82
83 pub fn format_duration(dur: Duration) -> String {
88 let nanos = dur.as_nanos() as f64;
89 if nanos < 1.0 {
90 return "0 microsecs".to_string();
91 }
92 let log10 = nanos.log10() as i32;
93 if log10 < 6 {
94 let precision = (2 - (log10 % 3)) as usize;
95 format!("{:.prec$} microsecs", nanos * 1.0e-3, prec = precision)
96 } else if log10 < 9 {
97 let precision = (2 - (log10 % 3)) as usize;
98 format!("{:.prec$} millisecs", nanos * 1.0e-6, prec = precision)
99 } else {
100 let precision = (2 - (log10 % 3)) as usize;
101 format!("{:.prec$} secs", nanos * 1.0e-9, prec = precision)
102 }
103 }
104
105 pub fn elapsed_str(&self) -> String {
107 Self::format_duration(self.elapsed())
108 }
109}
110
111impl Default for Timer {
112 fn default() -> Self {
113 Self::new(false)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use std::thread;
121
122 #[test]
123 fn test_timer_starts_running() {
124 let timer = Timer::new(false);
125 thread::sleep(Duration::from_millis(10));
126 assert!(timer.elapsed() >= Duration::from_millis(5));
127 }
128
129 #[test]
130 fn test_timer_starts_paused() {
131 let timer = Timer::new(true);
132 thread::sleep(Duration::from_millis(10));
133 assert!(timer.elapsed() < Duration::from_millis(1));
135 }
136
137 #[test]
138 fn test_timer_pause_resume() {
139 let mut timer = Timer::new(false);
140 thread::sleep(Duration::from_millis(20));
141 timer.pause();
142 let paused_elapsed = timer.elapsed();
143 thread::sleep(Duration::from_millis(20));
144 assert_eq!(timer.elapsed(), paused_elapsed);
146 timer.resume();
147 thread::sleep(Duration::from_millis(20));
148 assert!(timer.elapsed() > paused_elapsed);
149 }
150
151 #[test]
152 fn test_timer_restart() {
153 let mut timer = Timer::new(false);
154 thread::sleep(Duration::from_millis(20));
155 timer.restart();
156 assert!(timer.elapsed() < Duration::from_millis(5));
158 }
159
160 #[test]
161 fn test_format_duration_microsecs() {
162 let s = Timer::format_duration(Duration::from_micros(500));
163 assert!(s.contains("microsecs"));
164 }
165
166 #[test]
167 fn test_format_duration_millisecs() {
168 let s = Timer::format_duration(Duration::from_millis(50));
169 assert!(s.contains("millisecs"));
170 }
171
172 #[test]
173 fn test_format_duration_secs() {
174 let s = Timer::format_duration(Duration::from_secs(2));
175 assert!(s.contains("secs"));
176 }
177
178 #[test]
179 fn test_format_duration_zero() {
180 let s = Timer::format_duration(Duration::ZERO);
181 assert!(s.contains("microsecs"));
182 }
183
184 #[test]
185 fn test_default_timer_starts_running() {
186 let timer = Timer::default();
187 thread::sleep(Duration::from_millis(10));
188 assert!(timer.elapsed() >= Duration::from_millis(5));
189 }
190
191 #[test]
192 fn test_elapsed_nanos() {
193 let timer = Timer::new(false);
194 thread::sleep(Duration::from_millis(10));
195 assert!(timer.elapsed_nanos() > 1_000_000); }
197}