d3768aa7ca6441d2943c5ac080e57113ab9d957d
[rust-lightning] / lightning / src / util / time.rs
1 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
2 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
4 // You may not use this file except in accordance with one or both of these
5 // licenses.
6
7 //! [`Time`] trait and different implementations. Currently, it's mainly used in tests so we can
8 //! manually advance time.
9 //! Other crates may symlink this file to use it while [`Time`] trait is sealed here.
10
11 use core::ops::Sub;
12 use core::time::Duration;
13
14 /// A measurement of time.
15 pub trait Time: Copy + Sub<Duration, Output = Self> where Self: Sized {
16         /// Returns an instance corresponding to the current moment.
17         fn now() -> Self;
18
19         /// Returns the amount of time elapsed since `self` was created.
20         fn elapsed(&self) -> Duration;
21
22         /// Returns the amount of time passed between `earlier` and `self`.
23         fn duration_since(&self, earlier: Self) -> Duration;
24
25         /// Returns the amount of time passed since the beginning of [`Time`].
26         ///
27         /// Used during (de-)serialization.
28         fn duration_since_epoch() -> Duration;
29 }
30
31 /// A state in which time has no meaning.
32 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
33 pub struct Eternity;
34
35 impl Time for Eternity {
36         fn now() -> Self {
37                 Self
38         }
39
40         fn duration_since(&self, _earlier: Self) -> Duration {
41                 Duration::from_secs(0)
42         }
43
44         fn duration_since_epoch() -> Duration {
45                 Duration::from_secs(0)
46         }
47
48         fn elapsed(&self) -> Duration {
49                 Duration::from_secs(0)
50         }
51 }
52
53 impl Sub<Duration> for Eternity {
54         type Output = Self;
55
56         fn sub(self, _other: Duration) -> Self {
57                 self
58         }
59 }
60
61 #[cfg(not(feature = "no-std"))]
62 impl Time for std::time::Instant {
63         fn now() -> Self {
64                 std::time::Instant::now()
65         }
66
67         fn duration_since(&self, earlier: Self) -> Duration {
68                 self.duration_since(earlier)
69         }
70
71         fn duration_since_epoch() -> Duration {
72                 use std::time::SystemTime;
73                 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap()
74         }
75         fn elapsed(&self) -> Duration {
76                 std::time::Instant::elapsed(self)
77         }
78 }
79
80 #[cfg(test)]
81 pub mod tests {
82         use super::{Time, Eternity};
83
84         use core::time::Duration;
85         use core::ops::Sub;
86         use core::cell::Cell;
87
88         /// Time that can be advanced manually in tests.
89         #[derive(Clone, Copy, Debug, PartialEq, Eq)]
90         pub struct SinceEpoch(Duration);
91
92         impl SinceEpoch {
93                 thread_local! {
94                         static ELAPSED: Cell<Duration> = core::cell::Cell::new(Duration::from_secs(0));
95                 }
96
97                 pub fn advance(duration: Duration) {
98                         Self::ELAPSED.with(|elapsed| elapsed.set(elapsed.get() + duration))
99                 }
100         }
101
102         impl Time for SinceEpoch {
103                 fn now() -> Self {
104                         Self(Self::duration_since_epoch())
105                 }
106
107                 fn duration_since(&self, earlier: Self) -> Duration {
108                         self.0 - earlier.0
109                 }
110
111                 fn duration_since_epoch() -> Duration {
112                         Self::ELAPSED.with(|elapsed| elapsed.get())
113                 }
114
115                 fn elapsed(&self) -> Duration {
116                         Self::duration_since_epoch() - self.0
117                 }
118         }
119
120         impl Sub<Duration> for SinceEpoch {
121                 type Output = Self;
122
123                 fn sub(self, other: Duration) -> Self {
124                         Self(self.0 - other)
125                 }
126         }
127
128         #[test]
129         fn time_passes_when_advanced() {
130                 let now = SinceEpoch::now();
131                 assert_eq!(now.elapsed(), Duration::from_secs(0));
132
133                 SinceEpoch::advance(Duration::from_secs(1));
134                 SinceEpoch::advance(Duration::from_secs(1));
135
136                 let elapsed = now.elapsed();
137                 let later = SinceEpoch::now();
138
139                 assert_eq!(elapsed, Duration::from_secs(2));
140                 assert_eq!(later - elapsed, now);
141         }
142
143         #[test]
144         fn time_never_passes_in_an_eternity() {
145                 let now = Eternity::now();
146                 let elapsed = now.elapsed();
147                 let later = Eternity::now();
148
149                 assert_eq!(now.elapsed(), Duration::from_secs(0));
150                 assert_eq!(later - elapsed, now);
151         }
152 }