1#[cfg(feature = "testing")]
2use std::sync::{Arc, Mutex};
3
4use jiff::Timestamp;
5
6use crate::Instant;
7
8#[cfg(feature = "development")]
9mod shifted;
10
11#[derive(Clone, Debug, Default)]
13pub struct Clock {
14 pub(crate) source: Source,
15}
16
17#[derive(Clone, Debug, Default)]
18pub(crate) enum Source {
19 #[default]
20 System,
21 #[cfg(feature = "testing")]
22 Test(Arc<Mutex<Instant>>),
23 #[cfg(feature = "development")]
24 Shifted(jiff::SignedDuration),
25}
26
27impl Clock {
28 #[must_use]
29 pub fn system() -> Self {
30 Self::default()
31 }
32
33 #[must_use]
34 pub fn now(&self) -> Instant {
35 match &self.source {
36 Source::System => Instant::from(Timestamp::now()),
37 #[cfg(feature = "development")]
38 Source::Shifted(offset) => shifted::now(*offset),
39 #[cfg(feature = "testing")]
40 Source::Test(time) => *crate::unpoisoned::lock(time),
41 }
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn the_system_clock_follows_real_time() {
51 let before = Timestamp::now();
52
53 assert!(Clock::system().now().timestamp() >= before);
54 }
55}