1use std::fmt::Debug;
8use std::sync::Arc;
9use std::time::{Duration, SystemTime, UNIX_EPOCH};
10
11pub trait TimeSource: Debug + Send + Sync {
13    fn now(&self) -> SystemTime;
15}
16
17#[non_exhaustive]
19#[derive(Debug, Default)]
20pub struct SystemTimeSource;
21
22impl SystemTimeSource {
23    pub fn new() -> Self {
25        SystemTimeSource
26    }
27}
28
29impl TimeSource for SystemTimeSource {
30    fn now(&self) -> SystemTime {
31        #[allow(clippy::disallowed_methods)]
33        SystemTime::now()
34    }
35}
36
37impl Default for SharedTimeSource {
38    fn default() -> Self {
39        SharedTimeSource(Arc::new(SystemTimeSource))
40    }
41}
42
43#[derive(Debug)]
45pub struct StaticTimeSource {
46    time: SystemTime,
47}
48
49impl StaticTimeSource {
50    pub fn new(time: SystemTime) -> Self {
52        Self { time }
53    }
54
55    pub fn from_secs(epoch_secs: u64) -> Self {
57        Self::new(UNIX_EPOCH + Duration::from_secs(epoch_secs))
58    }
59}
60
61impl TimeSource for StaticTimeSource {
62    fn now(&self) -> SystemTime {
63        self.time
64    }
65}
66
67impl From<StaticTimeSource> for SharedTimeSource {
68    fn from(value: StaticTimeSource) -> Self {
69        SharedTimeSource::new(value)
70    }
71}
72
73#[derive(Debug, Clone)]
74pub struct SharedTimeSource(Arc<dyn TimeSource>);
78
79impl SharedTimeSource {
80    pub fn now(&self) -> SystemTime {
82        self.0.now()
83    }
84
85    pub fn new(source: impl TimeSource + 'static) -> Self {
87        Self(Arc::new(source))
88    }
89}
90
91impl TimeSource for SharedTimeSource {
92    fn now(&self) -> SystemTime {
93        self.0.now()
94    }
95}