1use crate::RollingTimer;
2use std::time::{Instant, Duration};
3
4use once_cell::sync::Lazy;
5static T0: Lazy<Instant> = Lazy::new(|| {
6 Instant::now()
7});
8
9#[derive(Default, Clone)]
10pub struct Timer<const TPS: u32>;
11
12impl<const TPS: u32> Timer<TPS> {
13 const NANOS_PER_TICK: u128 = 1_000_000_000 / (TPS as u128);
15
16 pub fn new() -> Self {
17 Timer
18 }
19}
20
21impl<const TPS: u32> RollingTimer for Timer<TPS>
22{
23 type Tick = u32;
24 const TICKS_PER_SECOND: Self::Tick = TPS;
25
26 fn is_initialized(&self) -> bool {
27 true
28 }
29
30 fn get_ticks(&self) -> Self::Tick {
31 let ticks = Instant::now()
32 .checked_duration_since(*T0)
33 .unwrap_or_else(|| Duration::from_secs(0));
34
35 let tnanos = ticks.as_nanos();
36 let div = tnanos / Self::NANOS_PER_TICK;
37 (div & 0xFFFF_FFFF) as u32
38 }
39}
40
41#[cfg(test)]
42mod test {
43 use super::Timer;
44 use std::time::{Instant, Duration};
45 use std::thread::sleep;
46 use crate::RollingTimer;
47
48 #[test]
49 fn sanity_test_1m() {
50 let timer: Timer<1_000_000> = Timer::new();
51 let start_gh = timer.get_ticks();
52 let start = Instant::now();
53 sleep(Duration::from_secs(1));
54 let stop_gh = timer.millis_since(start_gh);
55 let stop = start.elapsed();
56
57 assert!(
58 (stop >= Duration::from_millis(998))
59 && (stop <= Duration::from_millis(1002))
60 );
61 assert!(
62 (stop_gh >= 998) && (stop_gh <= 1002)
63 );
64 }
65
66 #[test]
67 fn sanity_test_1k() {
68 let timer: Timer<1_000> = Timer::new();
69 let start_gh = timer.get_ticks();
70 let start = Instant::now();
71 sleep(Duration::from_secs(1));
72 let stop_gh = timer.millis_since(start_gh);
73 let stop = start.elapsed();
74
75 assert!(
76 (stop >= Duration::from_millis(998))
77 && (stop <= Duration::from_millis(1002))
78 );
79 assert!(
80 (stop_gh >= 998) && (stop_gh <= 1002)
81 );
82 }
83
84 #[test]
85 fn sanity_test_330() {
86 let timer: Timer<330> = Timer::new();
87 let start_gh = timer.get_ticks();
88 let start = Instant::now();
89 sleep(Duration::from_secs(1));
90 let stop_gh = timer.millis_since(start_gh);
91 let stop = start.elapsed();
92
93 assert!(
94 (stop >= Duration::from_millis(998))
95 && (stop <= Duration::from_millis(1002))
96 );
97 assert!(
98 (stop_gh >= 998) && (stop_gh <= 1002)
99 );
100 }
101}