use std::cell::Cell;
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct Timer {
instant: Cell<Instant>,
duration: Duration,
}
impl Timer {
pub fn new() -> Timer {
Timer {
instant: Cell::new(Instant::now()),
duration: Duration::from_secs(0),
}
}
pub fn with_duration(duration: Duration) -> Timer {
let mut timer = Timer::new();
timer.duration = duration;
timer
}
pub fn reset(&self) {
self.instant.set(Instant::now());
}
pub fn expired(&self) -> bool {
self.instant.get().elapsed() >= self.duration
}
pub fn duration(&self) -> Duration {
self.duration
}
pub fn wait(&self) {
if let Some(duration) = self.duration.checked_sub(self.instant.get().elapsed()) {
std::thread::sleep(duration);
}
}
pub fn elapsed(&self) -> Duration {
self.instant.get().elapsed()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn wait_test() {
let timer = Timer::with_duration(Duration::from_millis(500));
timer.wait();
assert!(timer.elapsed().as_millis() >= 500);
}
#[test]
#[ignore]
fn wait_should_account_for_elapsed_time() {
let timer = Timer::with_duration(Duration::from_millis(50));
std::thread::sleep(Duration::from_millis(25));
let pre_wait = timer.elapsed();
timer.wait();
let diff = timer.elapsed() - pre_wait;
let diff = diff.as_millis();
assert!(diff < 50);
assert!(diff >= 25);
}
}