Skip to main content

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}