use std::fmt; use std::time::{Duration, Instant}; /// Stopwatch is a simple utility for measuring elapsed time. pub struct Stopwatch { /// The time when the stopwatch was started. start_time: Option, /// The total elapsed time. elapsed_time: Duration, } impl Stopwatch { /// Creates a new `Stopwatch` with initial values. /// /// # Examples /// /// ``` /// use std::time::Duration; /// use stopwatch::Stopwatch; /// /// let stopwatch = Stopwatch::new(); /// /// assert_eq!(stopwatch.elapsed(), Duration::from_secs(0)); /// ``` pub fn new() -> Stopwatch { Stopwatch { start_time: None, elapsed_time: Duration::from_secs(0), } } /// Starts the stopwatch. If the stopwatch is already running, this has no effect. /// /// # Examples /// /// ``` /// use stopwatch::Stopwatch; /// /// let mut stopwatch = Stopwatch::new(); /// /// stopwatch.start(); /// /// assert_eq!(stopwatch.is_running(), true); /// ``` pub fn start(&mut self) { if self.start_time.is_none() { self.start_time = Some(Instant::now()); } } /// Stops the stopwatch and adds the elapsed time since the start to the total elapsed time. /// If the stopwatch is not running, this has no effect. /// /// # Examples /// /// ``` /// use std::time::Duration; /// use stopwatch::Stopwatch; /// /// let mut stopwatch = Stopwatch::new(); /// /// stopwatch.start(); /// std::thread::sleep(std::time::Duration::from_secs(1)); /// stopwatch.stop(); /// /// assert!(!stopwatch.is_running()) /// ``` pub fn stop(&mut self) { if let Some(start_time) = self.start_time { self.elapsed_time += Instant::now() - start_time; self.start_time = None; } } /// Resets the stopwatch. If the stopwatch is currently running, stops it before resetting. /// /// # Examples /// /// ``` /// use std::time::Duration; /// use stopwatch::Stopwatch; /// /// let mut stopwatch = Stopwatch::new(); /// /// stopwatch.start(); /// std::thread::sleep(std::time::Duration::from_secs(1)); /// stopwatch.reset(); /// /// assert_eq!(stopwatch.elapsed(), Duration::from_secs(0)); /// ``` pub fn reset(&mut self) { if self.is_running() { self.stop(); } self.start_time = None; self.elapsed_time = Duration::from_secs(0); } /// Gets the total elapsed time. If the stopwatch is running, adds the time since the start. /// /// # Examples /// /// ``` /// use std::time::Duration; /// use stopwatch::Stopwatch; /// /// let mut stopwatch = Stopwatch::new(); /// /// stopwatch.start(); /// std::thread::sleep(Duration::from_secs(1)); /// /// assert_eq!(stopwatch.elapsed().as_secs(), 1); /// ``` pub fn elapsed(&self) -> Duration { if let Some(start_time) = self.start_time { if self.is_running() { return Instant::now().duration_since(start_time); } } self.elapsed_time } /// Checks if the stopwatch is currently running. /// /// # Examples /// /// ``` /// use std::time::Duration; /// use stopwatch::Stopwatch; /// /// let mut stopwatch = Stopwatch::new(); /// assert!(!stopwatch.is_running()); /// /// stopwatch.start(); /// assert!(stopwatch.is_running()); /// /// std::thread::sleep(Duration::from_secs(1)); /// /// stopwatch.stop(); /// assert!(!stopwatch.is_running()); /// ``` pub fn is_running(&self) -> bool { self.start_time.is_some() } } impl fmt::Display for Stopwatch { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:.2?}", self.elapsed()) } }