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/// Test utilities for clock simulation.
34#[cfg(any(test, feature = "test-dependencies"))]
35pub mod testing {
36 use std::sync::{Arc, RwLock};
37 use std::time::SystemTime;
38
39 use std::time::Duration;
40
41 use super::Clock;
42
43 /// A [`Clock`] impl that always returns a constant value for calls to [`now`].
44 ///
45 /// Calling `.clone()` on this clock will return a clock that shares the underlying storage and
46 /// uses a read-write lock to ensure serialized access to its [`tick`] method.
47 ///
48 /// [`now`]: Clock::now
49 /// [`tick`]: Self::tick
50 #[derive(Clone)]
51 pub struct FixedClock {
52 now: Arc<RwLock<SystemTime>>,
53 }
54
55 impl FixedClock {
56 /// Constructs a new [`FixedClock`] with the given time as the current instant.
57 pub fn new(now: SystemTime) -> Self {
58 Self {
59 now: Arc::new(RwLock::new(now)),
60 }
61 }
62
63 /// Updates the current time held by this [`FixedClock`] by adding the specified duration to
64 /// that instant.
65 pub fn tick(&self, delta: Duration) {
66 let mut w = self.now.write().unwrap();
67 *w += delta;
68 }
69 }
70
71 impl Clock for FixedClock {
72 fn now(&self) -> SystemTime {
73 *self.now.read().unwrap()
74 }
75 }
76}