zcash_client_sqlite/
util.rs

1//! Types that should be part of the standard library, but aren't.
2
3use std::time::SystemTime;
4
5/// A trait that represents the capability to read the system time.
6///
7/// Using implementations of this trait instead of accessing the system clock directly allows
8/// mocking with a controlled clock for testing purposes.
9pub trait Clock {
10    /// Returns the current system time, according to this clock.
11    fn now(&self) -> SystemTime;
12}
13
14/// A [`Clock`] impl that returns the current time according to the system clock.
15///
16/// This clock may be freely copied, as it is a zero-allocation type that simply delegates to
17/// [`SystemTime::now`] to return the current time.
18#[derive(Clone, Copy)]
19pub struct SystemClock;
20
21impl Clock for SystemClock {
22    fn now(&self) -> SystemTime {
23        SystemTime::now()
24    }
25}
26
27impl<C: Clock> Clock for &C {
28    fn now(&self) -> SystemTime {
29        (*self).now()
30    }
31}
32
33#[cfg(any(test, feature = "test-dependencies"))]
34pub mod testing {
35    use std::sync::{Arc, RwLock};
36    use std::time::SystemTime;
37
38    use std::time::Duration;
39
40    use super::Clock;
41
42    /// A [`Clock`] impl that always returns a constant value for calls to [`now`].
43    ///
44    /// Calling `.clone()` on this clock will return a clock that shares the underlying storage and
45    /// uses a read-write lock to ensure serialized access to its [`tick`] method.
46    ///
47    /// [`now`]: Clock::now
48    /// [`tick`]: Self::tick
49    #[derive(Clone)]
50    pub struct FixedClock {
51        now: Arc<RwLock<SystemTime>>,
52    }
53
54    impl FixedClock {
55        /// Constructs a new [`FixedClock`] with the given time as the current instant.
56        pub fn new(now: SystemTime) -> Self {
57            Self {
58                now: Arc::new(RwLock::new(now)),
59            }
60        }
61
62        /// Updates the current time held by this [`FixedClock`] by adding the specified duration to
63        /// that instant.
64        pub fn tick(&self, delta: Duration) {
65            let mut w = self.now.write().unwrap();
66            *w += delta;
67        }
68    }
69
70    impl Clock for FixedClock {
71        fn now(&self) -> SystemTime {
72            *self.now.read().unwrap()
73        }
74    }
75}