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}