index : stopwatch.git

ascending towards madness

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<Instant>,
    /// 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())
    }
}