1use crate::clock::Clock;
8use crate::instant::Instant;
9
10#[derive(Debug, PartialEq, Eq, Clone, Copy)]
12pub enum TimerError {
13 NotRunning,
15 Overflow,
17}
18
19#[derive(Debug, Clone, Copy)]
20struct Timing<I> {
21 start_time: I,
22 expiration_time: I,
23}
24
25#[derive(Debug)]
27pub struct Timer<'a, CLOCK>
28where
29 CLOCK: Clock,
30{
31 clock: &'a CLOCK,
33 timing: Option<Timing<CLOCK::Instant>>,
35}
36
37impl<'a, CLOCK> Timer<'a, CLOCK>
38where
39 CLOCK: Clock,
40{
41 pub fn new(clock: &'a CLOCK) -> Self {
43 Self {
44 clock,
45 timing: None,
46 }
47 }
48
49 pub fn duration(&self) -> Result<core::time::Duration, TimerError> {
51 if let Some(t) = &self.timing {
52 Ok(t.expiration_time.duration_since(t.start_time))
53 } else {
54 Err(TimerError::NotRunning)
55 }
56 }
57
58 pub fn is_running(&self) -> Result<bool, TimerError> {
61 if self.timing.is_some() {
62 self.is_expired().map(|expired| !expired)
63 } else {
64 Ok(false)
65 }
66 }
67
68 pub fn is_expired(&self) -> Result<bool, TimerError> {
71 if let Some(timing) = &self.timing {
72 let expired = self.clock.now() >= timing.expiration_time;
73 Ok(expired)
74 } else {
75 Err(TimerError::NotRunning)
76 }
77 }
78
79 pub fn duration_left(&self) -> Result<core::time::Duration, TimerError> {
82 if let Some(t) = &self.timing {
83 Ok(t.expiration_time.duration_since(self.clock.now()))
84 } else {
85 Err(TimerError::NotRunning)
86 }
87 }
88
89 pub fn try_start(&mut self, duration: core::time::Duration) -> Result<(), TimerError> {
91 let start_time = self.clock.now();
92 let expiration_time = start_time
93 .checked_add(duration)
94 .ok_or(TimerError::Overflow)?;
95
96 self.timing = Some(Timing {
97 start_time,
98 expiration_time,
99 });
100
101 Ok(())
102 }
103
104 pub fn try_wait(&mut self) -> nb::Result<(), TimerError> {
106 if self.is_expired()? {
107 self.timing = None;
108 Ok(())
109 } else {
110 Err(nb::Error::WouldBlock)
111 }
112 }
113
114 pub fn start(&mut self, duration: core::time::Duration) {
118 self.try_start(duration).expect("Could not start timer!");
120 }
121
122 pub fn wait(&mut self) -> nb::Result<(), void::Void> {
126 match self.try_wait() {
127 Err(nb::Error::Other(_)) => {
128 panic!("Error during wait for timer, probably not running!")
130 }
131 Ok(()) => Ok(()),
132 Err(nb::Error::WouldBlock) => Err(nb::Error::WouldBlock),
133 }
134 }
135
136 pub fn cancel(&mut self) -> Result<(), TimerError> {
138 if self.timing.is_some() && !self.is_expired()? {
139 self.timing = None;
140 Ok(())
141 } else {
142 self.timing = None;
143 Err(TimerError::NotRunning)
144 }
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use mockall::predicate::*;
151 use mockall::*;
152
153 use crate::clock::Clock;
154 use crate::instant::Instant32;
155
156 mock!(
157 MyClock {
158 }
159
160 impl Clock for MyClock {
161 type Instant = Instant32<1000>;
162 fn now(&self) -> Instant32<1000>;
163 }
164
165 impl core::fmt::Debug for MyClock {
166 fn fmt<'a>(&self, f: &mut core::fmt::Formatter<'a>) -> Result<(), core::fmt::Error> {
167 write!(f, "Clock Debug")
168 }
169 }
170 );
171
172 #[test]
173 fn test_clock_mock() {
174 let mut mymock = MockMyClock::new();
175
176 mymock
177 .expect_now()
178 .once()
179 .return_once(move || Instant32::new(23));
180 assert!(mymock.now() == Instant32::new(23));
181 }
182
183 #[test]
184 fn test_timer_basic() {
185 let mut clock = MockMyClock::new();
186
187 clock
188 .expect_now()
189 .times(5)
190 .returning(move || Instant32::new(0));
191 clock
192 .expect_now()
193 .times(2)
194 .returning(move || Instant32::new(10));
195
196 clock
197 .expect_now()
198 .times(5)
199 .returning(|| Instant32::new(1000));
200 clock
201 .expect_now()
202 .times(2)
203 .returning(move || Instant32::new(2001));
204
205 let mut timer: super::Timer<'_, _> = super::Timer::new(&clock);
207
208 assert_eq!(timer.is_running(), Ok(false));
209 assert_eq!(timer.duration(), Err(super::TimerError::NotRunning));
210 assert_eq!(
211 timer.try_wait(),
212 Err(nb::Error::Other(super::TimerError::NotRunning))
213 );
214
215 timer.start(core::time::Duration::from_millis(10));
217
218 assert_eq!(timer.is_running(), Ok(true));
219 assert_eq!(timer.duration(), Ok(core::time::Duration::from_millis(10)));
220 assert_eq!(
221 timer.duration_left(),
222 Ok(core::time::Duration::from_millis(10))
223 );
224
225 assert_eq!(timer.is_expired(), Ok(false)); assert_eq!(timer.wait(), Err(nb::Error::WouldBlock)); assert_eq!(timer.is_expired(), Ok(true)); assert_eq!(timer.wait(), Ok(())); assert_eq!(timer.is_running(), Ok(false)); timer.start(core::time::Duration::from_secs(1));
233 assert_eq!(timer.is_running(), Ok(true));
234 assert_eq!(
235 timer.duration(),
236 Ok(core::time::Duration::from_millis(1000))
237 );
238 assert_eq!(
239 timer.duration_left(),
240 Ok(core::time::Duration::from_millis(1000))
241 );
242
243 assert_eq!(timer.is_expired(), Ok(false)); assert_eq!(timer.wait(), Err(nb::Error::WouldBlock)); assert_eq!(timer.is_expired(), Ok(true)); assert_eq!(timer.wait(), Ok(())); assert_eq!(timer.is_running(), Ok(false)); }
249
250 #[test]
251 fn test_timer_cancel() {
252 let mut clock = MockMyClock::new();
253 clock
254 .expect_now()
255 .times(3)
256 .returning(move || Instant32::new(0));
257
258 let mut timer: super::Timer<'_, _> = super::Timer::new(&clock);
259
260 assert_eq!(timer.cancel(), Err(super::TimerError::NotRunning));
261
262 timer.start(core::time::Duration::from_millis(10));
263 assert_eq!(timer.is_running(), Ok(true));
264 assert_eq!(timer.cancel(), Ok(()));
265 assert_eq!(timer.is_running(), Ok(false));
266 assert_eq!(timer.is_expired(), Err(super::TimerError::NotRunning));
267 assert_eq!(timer.cancel(), Err(super::TimerError::NotRunning));
268 assert_eq!(timer.duration(), Err(super::TimerError::NotRunning));
269 assert_eq!(timer.duration_left(), Err(super::TimerError::NotRunning));
270 }
271}