breezy_timer_lib/
lib.rs

1use std::collections::HashMap;
2use cpu_time::ProcessTime;
3use std::time::Duration;
4
5pub type BreezyTimer = HashMap<&'static str, TimerState>;
6
7/// Structure used to keep track of the current process time since the last `start_timer!()` call,
8/// as well as the sum of all previously calculated times.
9#[derive(Debug, Eq, PartialEq, Clone)]
10pub struct TimerState {
11    process_time: ProcessTime,
12    total_elapsed: Duration
13}
14
15impl TimerState {
16    pub fn new() -> Self {
17        TimerState {
18            process_time: ProcessTime::now(),
19            total_elapsed: Duration::new(0, 0)
20        }
21    }
22
23    /// Helper function to add time up to a certain ProcessTime
24    pub fn add_time(&mut self, up_to: ProcessTime){
25        self.total_elapsed += up_to.duration_since(self.process_time);
26    }
27
28    /// Setter function to reset time to the given ProcessTime
29    pub fn reset_time(&mut self, new_time: ProcessTime){
30        self.process_time = new_time;
31    }
32
33    pub fn get_total_elapsed(&self) -> Duration {
34        self.total_elapsed.clone()
35    }
36}
37
38pub trait Timer {
39    /// Creates or updates a timer with the provided name. The same timer can be started and stopped
40    /// as many times as needed, and will keep track of the sum of all the time spent
41    fn start(&mut self, _: &'static str) { return }
42
43    /// Stops the timer with the provided name. The timer must already exist, or this call will panic.
44    /// The same timer can be started and stopped as many times as needed, and will keep track of the
45    /// sum of all the intervals
46    fn stop(&mut self, _: &'static str) { return }
47
48    fn elapsed(&self, _: &'static str) -> Option<Duration> { return None }
49}
50
51impl Timer for HashMap<&'static str, TimerState> {
52    #[cfg(feature="breezy_timer")]
53    fn start(&mut self, name: &'static str) {
54        self.entry(name)
55        .and_modify(|entry| entry.reset_time(ProcessTime::now()))
56        .or_insert(TimerState::new());
57    }
58
59    #[cfg(feature="breezy_timer")]
60    fn stop(&mut self, name: &'static str) {
61        let before = ProcessTime::now();
62        match self.get_mut(name) {
63            // todo: is there no better way than this?
64            //  problem with using the `log` crate is that the logger must be initialised upstream,
65            //  which is  a big assumption. Given that the feature should not be active for production
66            //  environment but only development, a print seems fair enough?
67            None => println!("Warning: timer {} was stopped but does not exist", name),
68            Some(entry) => {
69                entry.add_time(before);
70            }
71        }
72    }
73
74    #[cfg(feature="breezy_timer")]
75    fn elapsed(&self, name: &'static str) -> Option<Duration> {
76        match self.get(&name) {
77            None => None,
78            Some(ts) => Some(ts.total_elapsed)
79        }
80    }
81}