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}