vpp_sim/sim/
clock.rs

1/// A simulation clock that tracks steps over a fixed duration.
2///
3/// The `Clock` provides methods to advance time step-by-step or run
4/// a function at each time step until completion.
5///
6/// # Examples
7///
8/// Note: `vpp-sim` currently ships as a binary-first crate; this snippet is illustrative.
9/// ```ignore
10/// use vpp_sim::sim::clock::Clock;
11///
12/// let mut clock = Clock::new(3);
13/// let mut steps = Vec::new();
14///
15/// clock.run(|step| steps.push(step));
16/// assert_eq!(steps, vec![0, 1, 2]);
17/// ```
18pub struct Clock {
19    /// Current step of the simulation
20    current: usize,
21    /// Total steps to run in the simulation
22    total: usize,
23}
24
25impl Clock {
26    /// Creates a new clock with a specified total number of steps.
27    ///
28    /// # Arguments
29    ///
30    /// * `total` - The total number of steps the clock will run
31    pub fn new(total: usize) -> Self {
32        Self { current: 0, total }
33    }
34
35    /// Advances the clock by one step.
36    ///
37    /// # Returns
38    ///
39    /// * `Some(step)` - The current step number (starting from 0) before advancing
40    /// * `None` - If the clock has reached its total steps
41    pub fn tick(&mut self) -> Option<usize> {
42        if self.current < self.total {
43            let step = self.current;
44            self.current += 1;
45            Some(step)
46        } else {
47            None
48        }
49    }
50
51    /// Runs a function for each remaining step in the clock.
52    ///
53    /// This method will call the provided function with the current step
54    /// number for each step until the clock completes all steps.
55    ///
56    /// # Arguments
57    ///
58    /// * `f` - A function that takes the current step number as an argument
59    pub fn run<F>(&mut self, mut f: F)
60    where
61        F: FnMut(usize),
62    {
63        while let Some(step) = self.tick() {
64            f(step);
65        }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_new_clock() {
75        let clock = Clock::new(5);
76        assert_eq!(clock.current, 0);
77        assert_eq!(clock.total, 5);
78    }
79
80    #[test]
81    fn test_tick() {
82        let mut clock = Clock::new(2);
83        assert_eq!(clock.tick(), Some(0));
84        assert_eq!(clock.tick(), Some(1));
85        assert_eq!(clock.tick(), None);
86    }
87
88    #[test]
89    fn test_run() {
90        let mut clock = Clock::new(3);
91        let mut steps = Vec::new();
92
93        clock.run(|step| steps.push(step));
94
95        assert_eq!(steps, vec![0, 1, 2]);
96    }
97
98    #[test]
99    fn test_empty_clock() {
100        let mut clock = Clock::new(0);
101        assert_eq!(clock.tick(), None);
102
103        let mut was_called = false;
104        clock.run(|_| was_called = true);
105        assert!(!was_called);
106    }
107}