#![no_std]
#![warn(missing_docs)]
#[cfg(feature = "std")]
extern crate std;
cfg_if::cfg_if! {
if #[cfg(any(feature = "hifitime"))] {
use hifitime::{Duration, Epoch, TimeUnits, Unit};
#[cfg(feature = "derive_more")]
use derive_more::{Div, DivAssign, From, Into, Mul, MulAssign, Rem, Shl, Shr};
#[cfg_attr(
feature = "derive_more",
derive(From, Into, Mul, MulAssign, Div, DivAssign, Rem, Shr, Shl,)
)]
#[derive(Ord, Eq, PartialEq, PartialOrd, Clone, Copy, Debug, Hash)]
pub struct Stopwatch {
pub elapsed: Duration,
pub timer: Duration,
pub is_running: bool,
}
impl Display for Stopwatch {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.elapsed())
}
}
impl From<Duration> for Stopwatch {
fn from(dur: Duration) -> Self {
Self {
elapsed: dur,
timer: Epoch::now().unwrap().to_duration(),
is_running: false,
}
}
}
impl Default for Stopwatch {
fn default() -> Self {
Self {
elapsed: Duration::ZERO,
timer: Epoch::now().unwrap().to_duration(),
is_running: false,
}
}
}
impl Stopwatch {
pub fn start(&mut self) {
self.timer = Epoch::now().unwrap().to_duration();
self.is_running = true;
}
pub fn stop(&mut self) {
self.elapsed += (Epoch::now().unwrap().to_duration() - self.timer).abs();
self.is_running = false;
}
pub fn elapsed(&self) -> Duration {
match self.is_running {
true => self.elapsed + (Epoch::now().unwrap().to_duration() - self.timer).abs(),
false => self.elapsed,
}
}
pub fn elapsed_ms(&mut self) -> f64 {
self.elapsed().to_unit(Unit::Millisecond)
}
pub fn elapsed_ms_whole(&mut self) -> u128 {
self.elapsed().round(1.milliseconds()).to_unit(Unit::Millisecond).round() as u128
}
pub fn elapsed_us(&mut self) -> f64 {
self.elapsed().to_unit(Unit::Microsecond)
}
pub fn elapsed_us_whole(&mut self) -> u128 {
self.elapsed().round(1.microseconds()).to_unit(Unit::Microsecond).round() as u128
}
pub fn elapsed_ns(&mut self) -> f64 {
self.elapsed().to_unit(Unit::Nanosecond)
}
pub fn elapsed_ns_whole(&mut self) -> u128 {
self.elapsed().total_nanoseconds().try_into().unwrap()
}
pub fn elapsed_s(&mut self) -> f64 {
self.elapsed().to_unit(Unit::Second)
}
pub fn elapsed_s_whole(&self) -> u64 {
self.elapsed().round(1.seconds()).to_seconds().round() as u64
}
}
} else if #[cfg(feature = "stdtime")] {
use core::time::Duration;
#[cfg(feature = "std")]
use std::time::Instant;
#[cfg(feature = "derive_more")]
use derive_more::{Div, DivAssign, From, Into, Mul, MulAssign, Rem, Shl, Shr};
#[cfg_attr(
feature = "derive_more",
derive(From, Into, Mul, MulAssign, Div, DivAssign, Rem, Shr, Shl,)
)]
#[derive(Ord, Eq, PartialEq, PartialOrd, Clone, Copy, Debug, Hash)]
pub struct Stopwatch {
pub elapsed: Duration,
pub timer: Instant,
pub is_running: bool,
}
impl Display for Stopwatch {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let elapsed_ms = self.clone().elapsed_ms_whole();
write!(f, "{elapsed_ms}ms")
}
}
impl From<Duration> for Stopwatch {
fn from(dur: Duration) -> Self {
Self {
elapsed: dur,
timer: Instant::now(),
is_running: false,
}
}
}
impl Default for Stopwatch {
fn default() -> Self {
Self {
elapsed: Duration::new(0, 0),
timer: Instant::now(),
is_running: false,
}
}
}
impl Stopwatch {
pub fn start(&mut self) {
self.timer = Instant::now();
self.is_running = true;
}
pub fn stop(&mut self) {
self.elapsed += self.timer.elapsed();
self.is_running = false;
}
pub fn elapsed(&self) -> Duration {
match self.is_running {
true => self.elapsed + self.timer.elapsed(),
false => self.elapsed,
}
}
pub fn elapsed_ms_whole(&mut self) -> u128 {
self.elapsed().as_millis()
}
pub fn elapsed_us_whole(&mut self) -> u128 {
self.elapsed().as_micros()
}
pub fn elapsed_ns_whole(&mut self) -> u128 {
self.elapsed().as_nanos()
}
pub fn elapsed_s(&mut self) -> f64 {
self.elapsed().as_secs_f64()
}
pub fn elapsed_s_whole(&self) -> u64 {
self.elapsed().as_secs()
}
}
} else {
compile_error!("You must enable either the `stdtime` or `hifitime` feature.");
}
}
use core::fmt::{Display, Formatter};
impl From<Stopwatch> for Duration {
fn from(sw: Stopwatch) -> Self {
sw.elapsed()
}
}
impl Stopwatch {
pub fn new() -> Stopwatch {
Stopwatch::default()
}
pub fn start_new() -> Stopwatch {
let mut sw = Stopwatch::new();
sw.start();
sw
}
pub fn reset(&mut self) {
*self = Stopwatch::new();
}
pub fn restart(&mut self) {
self.reset();
self.start();
}
pub fn is_running(&mut self) -> bool {
self.is_running
}
}