Remove "no-std" feature checks
[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 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
62 #[cfg(feature = "std")]
63 pub struct MonotonicTime(std::time::Instant);
64
65 /// The amount of time to shift `Instant` forward to prevent overflow when subtracting a `Duration`
66 /// from `Instant::now` on some operating systems (e.g., iOS representing `Instance` as `u64`).
67 #[cfg(feature = "std")]
68 const SHIFT: Duration = Duration::from_secs(10 * 365 * 24 * 60 * 60); // 10 years.
69
70 #[cfg(feature = "std")]
71 impl Time for MonotonicTime {
72         fn now() -> Self {
73                 let instant = std::time::Instant::now().checked_add(SHIFT).expect("Overflow on MonotonicTime instantiation");
74                 Self(instant)
75         }
76
77         fn duration_since(&self, earlier: Self) -> Duration {
78                 // On rust prior to 1.60 `Instant::duration_since` will panic if time goes backwards.
79                 // However, we support rust versions prior to 1.60 and some users appear to have "monotonic
80                 // clocks" that go backwards in practice (likely relatively ancient kernels/etc). Thus, we
81                 // manually check for time going backwards here and return a duration of zero in that case.
82                 let now = Self::now();
83                 if now.0 > earlier.0 { now.0 - earlier.0 } else { Duration::from_secs(0) }
84         }
85
86         fn duration_since_epoch() -> Duration {
87                 use std::time::SystemTime;
88                 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap()
89         }
90
91         fn elapsed(&self) -> Duration {
92                 Self::now().0 - self.0
93         }
94 }
95
96 #[cfg(feature = "std")]
97 impl Sub<Duration> for MonotonicTime {
98         type Output = Self;
99
100         fn sub(self, other: Duration) -> Self {
101                 let instant = self.0.checked_sub(other).expect("MonotonicTime is not supposed to go backward futher than 10 years");
102                 Self(instant)
103         }
104 }
105
106 #[cfg(test)]
107 pub mod tests {
108         use super::{Time, Eternity};
109
110         use core::time::Duration;
111         use core::ops::Sub;
112         use core::cell::Cell;
113
114         /// Time that can be advanced manually in tests.
115         #[derive(Clone, Copy, Debug, PartialEq, Eq)]
116         pub struct SinceEpoch(Duration);
117
118         impl SinceEpoch {
119                 thread_local! {
120                         static ELAPSED: Cell<Duration> = core::cell::Cell::new(Duration::from_secs(0));
121                 }
122
123                 pub fn advance(duration: Duration) {
124                         Self::ELAPSED.with(|elapsed| elapsed.set(elapsed.get() + duration))
125                 }
126         }
127
128         impl Time for SinceEpoch {
129                 fn now() -> Self {
130                         Self(Self::duration_since_epoch())
131                 }
132
133                 fn duration_since(&self, earlier: Self) -> Duration {
134                         self.0 - earlier.0
135                 }
136
137                 fn duration_since_epoch() -> Duration {
138                         Self::ELAPSED.with(|elapsed| elapsed.get())
139                 }
140
141                 fn elapsed(&self) -> Duration {
142                         Self::duration_since_epoch() - self.0
143                 }
144         }
145
146         impl Sub<Duration> for SinceEpoch {
147                 type Output = Self;
148
149                 fn sub(self, other: Duration) -> Self {
150                         Self(self.0 - other)
151                 }
152         }
153
154         #[test]
155         fn time_passes_when_advanced() {
156                 let now = SinceEpoch::now();
157                 assert_eq!(now.elapsed(), Duration::from_secs(0));
158
159                 SinceEpoch::advance(Duration::from_secs(1));
160                 SinceEpoch::advance(Duration::from_secs(1));
161
162                 let elapsed = now.elapsed();
163                 let later = SinceEpoch::now();
164
165                 assert_eq!(elapsed, Duration::from_secs(2));
166                 assert_eq!(later - elapsed, now);
167         }
168
169         #[test]
170         fn time_never_passes_in_an_eternity() {
171                 let now = Eternity::now();
172                 let elapsed = now.elapsed();
173                 let later = Eternity::now();
174
175                 assert_eq!(now.elapsed(), Duration::from_secs(0));
176                 assert_eq!(later - elapsed, now);
177         }
178
179         #[test]
180         #[cfg(feature = "std")]
181         fn monotonic_time_subtracts() {
182                 let now = super::MonotonicTime::now();
183                 assert!(now.elapsed() < Duration::from_secs(10));
184
185                 let ten_years = Duration::from_secs(10 * 365 * 24 * 60 * 60);
186                 let past = now - ten_years;
187                 assert!(past.elapsed() >= ten_years);
188         }
189 }