chronometer/lib.rs
1use std::time::{Duration, Instant};
2
3pub struct Chronometer {
4 chrono: Option<Instant>,
5 old: Option<Duration>,
6
7 /// Vector of all the laps since last reset
8 pub laps: Vec<Duration>,
9
10 /// Has the chronometer started yet
11 pub started: bool,
12
13 /// Is the chronometer in pause mode
14 pub paused: bool,
15}
16
17impl Chronometer {
18 /// Create a new Chronometer
19 ///
20 /// # Examples
21 ///
22 /// Basic usage:
23 ///
24 /// ```
25 /// use chronometer::Chronometer;
26 ///
27 /// let mut chrono = Chronometer::new();
28 /// ```
29 pub fn new() -> Chronometer {
30 Chronometer {
31 chrono: None,
32 old: None,
33 started: false,
34 paused: false,
35 laps: vec![],
36 }
37 }
38
39 /// Start and "unpause" the chronometer
40 ///
41 /// # Examples
42 ///
43 /// Basic usage:
44 ///
45 /// ```
46 /// chrono.start();
47 /// ```
48 pub fn start(&mut self) {
49 self.chrono = Some(Instant::now());
50 self.started = true;
51 self.paused = false;
52 }
53
54 /// Pause the chronometer
55 ///
56 /// # Examples
57 ///
58 /// Basic usage:
59 ///
60 /// ```
61 /// chrono.start();
62 ///
63 /// let time = time::Duration::from_millis(100);
64 ///
65 /// thread::sleep(time);
66 /// chrono.pause(); // chrono.duration == Duration<0.1s>
67 /// thread::sleep(time);
68 ///
69 /// // chrono.duration == Duration<0.1s>
70 ///
71 /// chrono.start();
72 /// thread::sleep(time);
73 /// // chrono.duration == Duration<0.2s>
74 /// ```
75 pub fn pause(&mut self) {
76 self.old = match self.chrono {
77 Some(chrono) => match self.old {
78 Some(old) => Some(chrono.elapsed() + old),
79 None => Some(chrono.elapsed()),
80 },
81 None => None,
82 };
83 self.chrono = None;
84 self.paused = true;
85 }
86
87 /// Add a lap to the chronometer
88 ///
89 /// # Examples
90 ///
91 /// Basic usage:
92 ///
93 /// ```
94 /// chrono.start();
95 ///
96 /// let time = time::Duration::from_millis(100);
97 ///
98 /// thread::sleep(time);
99 ///
100 /// chrono.lap(); // chono.laps == [Duration<0.1s>, Duration<0.2s>]
101 ///
102 /// thread::sleep(time);
103 ///
104 /// chrono.lap(); // chono.laps == [Duration<0.1s>, Duration<0.2s>]
105 /// ```
106 pub fn lap(&mut self) {
107 if let Some(chrono) = self.chrono {
108 self.laps.push(chrono.elapsed());
109 }
110 }
111
112 /// Reset the chronometer, useful to restart everything and all the mesurements in your program
113 ///
114 /// # Examples
115 ///
116 /// Basic usage:
117 ///
118 /// ```
119 /// chrono.start();
120 ///
121 /// let time = time::Duration::from_millis(100);
122 ///
123 /// thread::sleep(time);
124 ///
125 /// chrono.lap(); // chono.laps == [Duration<0.1s>, Duration<0.2s>]
126 /// chrono.reset();
127 /// // chono == {
128 /// // started: false,
129 /// // paused: false,
130 /// // laps: vec![],
131 /// // }
132 /// ```
133 pub fn reset(&mut self) {
134 self.chrono = None;
135 self.paused = false;
136 self.started = false;
137 self.old = None;
138 self.laps = vec![]
139 }
140
141 /// Gets you the elapsed time on your chronometer as a std::time::Duration
142 ///
143 /// # Examples
144 ///
145 /// Basic usage:
146 ///
147 /// ```
148 /// chrono.start();
149 ///
150 /// let time = time::Duration::from_millis(100);
151 ///
152 /// thread::sleep(time);
153 ///
154 /// println!("elapsed: {}", chrono.duration().as_millis()); // elapsed: 100
155 /// ```
156 pub fn duration(&self) -> Option<Duration> {
157 if self.started {
158 if self.paused {
159 self.old
160 } else {
161 match self.chrono {
162 Some(chrono) => match self.old {
163 Some(old) => Some(chrono.elapsed() + old),
164 None => Some(chrono.elapsed()),
165 },
166 None => None,
167 }
168 }
169 } else {
170 None
171 }
172 }
173}
174
175/// Displays the current duration as milliseconds
176impl std::fmt::Display for Chronometer {
177 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
178 match self.duration() {
179 Some(duration) => write!(f, "{}", duration.as_millis()),
180 None => write!(f, "<not started>"),
181 }
182 }
183}
184
185/// Displays all the public chronometer informations
186impl std::fmt::Debug for Chronometer {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
188 write!(f, "<Chronometer {{ started: {}, paused: {}, laps: {}, current value: {:?} }}>", self.started, self.paused, self.laps.len(), match self.duration() {
189 Some(duration) => duration,
190 None => std::time::Duration::new(0, 0),
191 })
192 }
193}
194
195
196#[cfg(test)]
197mod test {
198 use super::Chronometer;
199
200 #[test]
201 fn create() {
202 let chrono = Chronometer::new();
203
204 assert_eq!(chrono.started, false);
205 assert_eq!(chrono.paused, false);
206
207 assert_eq!(chrono.chrono, None);
208 assert_eq!(chrono.laps, vec![]);
209
210 assert_eq!(chrono.duration(), None);
211 }
212
213 #[test]
214 fn start() {
215 let mut chrono = Chronometer::new();
216
217 chrono.start();
218
219 assert_eq!(chrono.started, true);
220 assert_eq!(chrono.paused, false);
221
222 assert_ne!(chrono.chrono, None);
223
224 std::thread::sleep(std::time::Duration::from_millis(100));
225
226 match chrono.duration() {
227 Some(duration) => assert_eq!(duration.as_millis() > 0, true),
228 None => assert_eq!(true, false),
229 }
230 }
231
232 #[test]
233 fn pause() {
234 let mut chrono = Chronometer::new();
235
236 chrono.start();
237
238 assert_eq!(chrono.started, true);
239 assert_eq!(chrono.paused, false);
240
241 let time_before_pause = match chrono.duration() {
242 Some(duration) => duration.as_millis(),
243 None => 10000,
244 };
245
246 chrono.pause();
247
248 assert_eq!(chrono.started, true);
249 assert_eq!(chrono.paused, true);
250
251 let time_after_pause = match chrono.duration() {
252 Some(duration) => duration.as_millis(),
253 None => 10000,
254 };
255
256 assert_eq!(time_before_pause, time_after_pause);
257 }
258}