@@ -58,10 +58,20 @@ impl Sub<Duration> for Eternity {
58
58
}
59
59
}
60
60
61
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
62
+ #[ cfg( not( feature = "no-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( not( feature = "no-std" ) ) ]
68
+ const SHIFT : Duration = Duration :: from_secs ( 10 * 365 * 24 * 60 * 60 ) ; // 10 years.
69
+
61
70
#[ cfg( not( feature = "no-std" ) ) ]
62
- impl Time for std :: time :: Instant {
71
+ impl Time for MonotonicTime {
63
72
fn now ( ) -> Self {
64
- std:: time:: Instant :: now ( )
73
+ let instant = std:: time:: Instant :: now ( ) . checked_add ( SHIFT ) . expect ( "Overflow on MonotonicTime instantiation" ) ;
74
+ Self ( instant)
65
75
}
66
76
67
77
fn duration_since ( & self , earlier : Self ) -> Duration {
@@ -70,15 +80,26 @@ impl Time for std::time::Instant {
70
80
// clocks" that go backwards in practice (likely relatively ancient kernels/etc). Thus, we
71
81
// manually check for time going backwards here and return a duration of zero in that case.
72
82
let now = Self :: now ( ) ;
73
- if now > earlier { now - earlier } else { Duration :: from_secs ( 0 ) }
83
+ if now. 0 > earlier. 0 { now. 0 - earlier. 0 } else { Duration :: from_secs ( 0 ) }
74
84
}
75
85
76
86
fn duration_since_epoch ( ) -> Duration {
77
87
use std:: time:: SystemTime ;
78
88
SystemTime :: now ( ) . duration_since ( SystemTime :: UNIX_EPOCH ) . unwrap ( )
79
89
}
90
+
80
91
fn elapsed ( & self ) -> Duration {
81
- std:: time:: Instant :: elapsed ( self )
92
+ Self :: now ( ) . 0 - self . 0
93
+ }
94
+ }
95
+
96
+ #[ cfg( not( feature = "no-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)
82
103
}
83
104
}
84
105
@@ -154,4 +175,15 @@ pub mod tests {
154
175
assert_eq ! ( now. elapsed( ) , Duration :: from_secs( 0 ) ) ;
155
176
assert_eq ! ( later - elapsed, now) ;
156
177
}
178
+
179
+ #[ test]
180
+ #[ cfg( not( feature = "no-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
+ }
157
189
}
0 commit comments