use std::fmt;
use time;
#[derive(Clone, Debug, Default)]
pub struct Stopwatch {
laps: Vec<u64>,
start_time: Option<u64>,
total_time: u64
}
impl Stopwatch {
pub fn new() -> Stopwatch {
Stopwatch { laps: vec![], start_time: None, total_time: 0 }
}
pub fn start_new() -> Stopwatch {
let mut stopwatch = Stopwatch::new();
stopwatch.start();
stopwatch
}
pub fn start(&mut self) {
self.start_time = Some(time::precise_time_ns());
}
pub fn lap(&mut self) -> u64 {
let current_time: u64 = time::precise_time_ns();
let lap: u64 = match self.start_time {
Some(t) => current_time - t,
None => return 0
};
self.total_time += lap;
self.laps.push(lap);
self.start_time = Some(current_time);
lap
}
pub fn stop(&mut self) {
self.start_time = None;
}
pub fn reset(&mut self) {
self.laps = vec![];
self.start_time = None;
self.total_time = 0;
}
pub fn restart(&mut self) {
self.reset();
self.start();
}
pub fn total_time(&self) -> u64 {
match self.start_time {
Some(current_lap_start_time) => {
let current_time: u64 = time::precise_time_ns();
let lap: u64 = current_time - current_lap_start_time;
self.total_time + lap
},
None => self.total_time
}
}
pub fn laps(&self) -> &Vec<u64> {
&self.laps
}
pub fn number_of_laps(&self) -> usize {
self.laps.len()
}
pub fn is_running(&self) -> bool {
self.start_time.is_some()
}
}
impl fmt::Display for Stopwatch {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{total_time}ns", total_time = self.total_time())
}
}
#[cfg(test)]
mod tests {
#![allow(unused_results)]
use super::Stopwatch;
#[test]
fn new() {
let stopwatch = Stopwatch::new();
assert_eq!(stopwatch.laps, vec![]);
assert_eq!(stopwatch.start_time, None);
assert_eq!(stopwatch.total_time, 0);
}
#[test]
fn start_new() {
let stopwatch = Stopwatch::start_new();
assert_eq!(stopwatch.laps, vec![]);
assert!(stopwatch.start_time.is_some());
assert_eq!(stopwatch.total_time, 0);
}
#[test]
fn start() {
let mut stopwatch = Stopwatch::new();
stopwatch.start();
assert!(stopwatch.start_time.is_some());
}
#[test]
fn lap() {
let mut stopwatch = Stopwatch::new();
let lap_0: u64 = stopwatch.lap();
assert_eq!(lap_0, 0);
assert_eq!(stopwatch.laps.len(), 0);
assert_eq!(stopwatch.total_time, lap_0);
stopwatch.start();
let lap_1: u64 = stopwatch.lap();
assert!(lap_1 > 0);
assert_eq!(stopwatch.laps.len(), 1);
assert_eq!(stopwatch.laps[0], lap_1);
assert_eq!(stopwatch.total_time, lap_1);
let lap_2: u64 = stopwatch.lap();
assert!(lap_2 > 0);
assert_eq!(stopwatch.laps.len(), 2);
assert_eq!(stopwatch.laps[0], lap_1);
assert_eq!(stopwatch.laps[1], lap_2);
assert_eq!(stopwatch.total_time, lap_1 + lap_2);
}
#[test]
fn stop() {
let mut stopwatch = Stopwatch::start_new();
let lap: u64 = stopwatch.lap();
stopwatch.stop();
assert!(stopwatch.start_time.is_none());
assert_eq!(stopwatch.laps.len(), 1);
assert_eq!(stopwatch.total_time, lap);
}
#[test]
fn reset() {
let mut stopwatch = Stopwatch::start_new();
stopwatch.lap();
stopwatch.reset();
assert_eq!(stopwatch.laps, vec![]);
assert_eq!(stopwatch.start_time, None);
assert_eq!(stopwatch.total_time, 0);
}
#[test]
fn restart() {
let mut stopwatch = Stopwatch::start_new();
stopwatch.lap();
stopwatch.restart();
assert_eq!(stopwatch.laps, vec![]);
assert!(stopwatch.start_time.is_some());
assert_eq!(stopwatch.total_time, 0);
}
#[test]
fn total_time() {
let mut stopwatch = Stopwatch::start_new();
let start_time: u64 = stopwatch.start_time.unwrap();
let mut total_time: u64 = stopwatch.total_time();
assert!(total_time > 0);
assert_eq!(stopwatch.total_time, 0);
assert_eq!(stopwatch.laps, vec![]);
assert_eq!(stopwatch.start_time.unwrap(), start_time);
stopwatch.lap();
stopwatch.stop();
total_time = stopwatch.total_time();
assert_eq!(total_time, stopwatch.total_time);
}
#[test]
fn laps() {
let mut stopwatch = Stopwatch::start_new();
stopwatch.lap();
stopwatch.lap();
stopwatch.lap();
assert_eq!(stopwatch.laps(), &stopwatch.laps);
}
#[test]
fn number_of_laps() {
let mut stopwatch = Stopwatch::start_new();
stopwatch.lap();
stopwatch.lap();
stopwatch.lap();
assert_eq!(stopwatch.number_of_laps(), 3);
}
#[test]
fn is_running() {
let mut stopwatch = Stopwatch::new();
assert!(!stopwatch.is_running());
stopwatch.start();
assert!(stopwatch.is_running());
}
#[test]
fn fmt_display() {
let mut stopwatch = Stopwatch::new();
stopwatch.total_time = 42;
assert_eq!(format!("{stopwatch}", stopwatch = stopwatch), "42ns");
}
}