mod display;
use std::time::Instant;
pub struct Timer {
pub start_time: Instant,
pub task_name: String,
}
impl Default for Timer {
#[inline]
fn default() -> Self {
Timer::new("")
}
}
impl std::fmt::Debug for Timer {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.elapsed_str())
}
}
impl std::fmt::Display for Timer {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.elapsed_str())
}
}
impl Timer {
#[inline]
pub fn new(task_name: &str) -> Self {
Timer {
start_time: Instant::now(),
task_name: task_name.to_string(),
}
}
#[inline]
pub fn restart(&mut self, task_name: &str) {
self.start_time = Instant::now();
self.task_name = task_name.to_string();
}
#[inline]
pub fn duration(&self) -> std::time::Duration {
self.start_time.elapsed()
}
#[inline]
pub fn duration_str(&self) -> String {
display::format_duration(self.duration())
}
#[inline]
pub fn elapsed_str(&self) -> String {
format!("{} elapsed {}", self.task_name, self.duration_str())
}
#[inline]
pub fn took_str(&self) -> String {
format!("{} took {}", self.task_name, self.duration_str())
}
#[inline]
pub fn elapsed(&self) {
println!("{}", self.elapsed_str());
}
#[inline]
pub fn stop(self) {
println!("{}", self.took_str());
}
#[inline]
#[cfg(feature = "log")]
pub fn log(&self) {
log::info!("{}", self.elapsed_str());
}
}
#[inline]
pub fn took<F: FnOnce() -> R, R>(f: F, task_name: &str) -> R {
let timer = Timer::new(task_name);
let result = f();
timer.stop();
result
}
#[inline]
pub fn ltook<F: FnOnce() -> R, R>(f: F, task_name: &str) -> R {
let timer = Timer::new(task_name);
let result = f();
timer.log();
result
}
#[macro_export]
macro_rules! took {
($($tt:tt)*) => {
{
let timer = $crate::Timer::new("");
let res = {$($tt)*};
timer.stop();
res
}
};
}
#[macro_export]
macro_rules! ltook {
($($tt:tt)*) => {
{
let timer = $crate::Timer::new("");
let res = {$($tt)*};
timer.log();
res
}
};
}
#[cfg(test)]
mod tests {
use super::*;
use std::thread::sleep;
use std::time::Duration;
#[test]
fn test_timer_new() {
let timer = Timer::new("Test Task");
assert_eq!(timer.task_name, "Test Task");
}
#[test]
fn test_timer_restart() {
let mut timer = Timer::new("Task 1");
timer.restart("Task 2");
assert_eq!(timer.task_name, "Task 2");
}
#[test]
fn test_timer_duration() {
let timer = Timer::new("Duration Test");
sleep(Duration::from_millis(10));
assert!(timer.duration().as_millis() >= 10);
}
#[test]
fn test_timer_duration_str() {
let timer = Timer::new("Duration Str Test");
sleep(Duration::from_millis(10));
assert!(timer.duration_str().contains("ms"));
}
#[test]
fn test_timer_default() {
let timer = Timer::default();
assert_eq!(timer.task_name, "");
}
#[test]
fn test_took() {
let result = took(
|| {
sleep(Duration::from_millis(10));
42
},
"Test Task",
);
assert_eq!(result, 42);
}
#[test]
fn test_took_macro() {
let result = took! {
sleep(Duration::from_millis(10));
42
};
assert_eq!(result, 42);
}
}