sprocket_engine 0.2.1

A vulkan game engine
Documentation
use std::time::{Duration, Instant};

/// A general purpose timer for measuring execution time or checking if a certain time has passed
/// Timer can be stopped and this will stop time from being counted
/// A timer can also have a target sets and can be queried if that target has been passed
pub struct Timer {
    start: Instant,
    // An optional target that will signal the timer if set
    target: Option<Duration>,
    // Stores the instant when stopped or None
    stopped: Option<Duration>,
}

impl Timer {
    /// Starts a new timer without a target
    pub fn new() -> Self {
        Timer {
            start: Instant::now(),
            target: None,
            stopped: None,
        }
    }

    /// Creates a new timer which is going to be signaled after specified duration
    pub fn with_target(duration: Duration) -> Self {
        Timer {
            start: Instant::now(),
            target: Some(duration),
            stopped: None,
        }
    }

    /// Sets a target for timer
    /// Replaces an old one
    /// Does not reset a timer. Target can be immediately passed
    /// Signaled state reflects the new target
    pub fn set_target(&mut self, target: Option<Duration>) {
        self.target = target
    }

    /// Returns the current target for the timer
    pub fn target(&self) -> Option<Duration> {
        self.target
    }

    /// Returns the current duration of the timer
    /// If called on a stopped timer, it return that when it was stopped
    pub fn duration(&self) -> Duration {
        match self.stopped {
            None => Instant::now().saturating_duration_since(self.start),
            Some(duration) => duration,
        }
    }

    /// Stops the timer and returns the duration
    /// The duration can be retrieved again with Timer::duration()
    pub fn stop(&mut self) -> Duration {
        self.stopped = Some(Instant::now().saturating_duration_since(self.start));
        self.stopped.unwrap()
    }

    /// Restarts a stopped timer
    /// Makes the timer be signaled again after target time from now
    pub fn reset(&mut self) {
        self.start = Instant::now();
        self.stopped = None
    }

    /// Returns true if the timer is currently running
    pub fn running(&self) -> bool {
        self.stopped.is_none()
    }

    /// Returns true if the timer is currently stopped
    /// The opposite of Timer::running()
    pub fn stopped(&self) -> bool {
        self.stopped.is_some()
    }

    /// Returns true if the timer has passed the target
    pub fn signaled(&self) -> bool {
        match self.target {
            Some(target) => self.duration() >= target,
            None => false,
        }
    }

    /// Returns the time to the target if any
    /// Returns None if target is None, target has passed, or timer is stopped
    pub fn remaining(&self) -> Option<Duration> {
        if self.stopped.is_some() {
            return None;
        }

        match self.target {
            Some(target) => {
                target.checked_sub(Instant::now().saturating_duration_since(self.start))
            }
            None => None,
        }
    }

    /// Returns the time in whole milliseconds to the target if any
    /// Returns None if target is None, target has passed, or timer is stopped
    pub fn remaining_ms(&self) -> Option<usize> {
        self.remaining().map(|d| d.as_millis() as usize)
    }

    /// Returns the time in whole microseconds to the target if any
    /// Returns None if target is None, target has passed, or timer is stopped
    pub fn remaining_us(&self) -> Option<usize> {
        self.remaining().map(|d| d.as_micros() as usize)
    }

    /// Returns the time in fractional seconds to the target if any
    /// Returns None if target is None, target has passed, or timer is stopped
    pub fn remaining_f32(&self) -> Option<f32> {
        self.remaining().map(|d| d.as_secs_f32())
    }
}