1use std::{
2 fmt::Debug,
3 time::{Duration, Instant},
4};
5
6pub trait Tick {
7 fn try_tick(&mut self);
8}
9
10pub struct TickState {
11 start: Instant,
12 last_tick: Duration,
13 tick: Duration,
14}
15
16impl Debug for TickState {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("TickMachine")
19 .field("tick", &self.tick)
20 .finish()
21 }
22}
23
24impl TickState {
25 pub fn new(tick: Duration) -> Self {
26 Self {
27 start: Instant::now(),
28 last_tick: Duration::ZERO,
29 tick,
30 }
31 }
32
33 pub fn try_tick<F>(&mut self, f: F)
34 where
35 F: FnOnce(),
36 {
37 if self.start.elapsed() - self.last_tick >= self.tick {
38 f();
39 self.last_tick += self.tick;
40 }
41 }
42}
43
44pub struct TickMachine<F> {
45 f: F,
46 tick: TickState,
47}
48
49impl<F: Fn()> TickMachine<F> {
50 pub fn new(tick: TickState, f: F) -> TickMachine<F> {
51 TickMachine { f, tick }
52 }
53}
54
55impl<F: Fn()> Tick for TickMachine<F> {
56 fn try_tick(&mut self) {
57 self.tick.try_tick(|| (self.f)());
58 }
59}
60
61#[cfg(test)]
62mod test {
63 use std::time::Duration;
64
65 use crate::{Tick, TickMachine, TickState};
66
67 #[test]
68 fn test() {
69 let tick = Duration::from_millis(50);
70 let tick = TickState::new(tick);
71 let mut machine = TickMachine::new(tick, || {});
72 machine.try_tick();
73 }
74}