44// You may not use this file except in accordance with one or both of these
55// licenses.
66
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 passed between `earlier` and `self`.
20- fn duration_since ( & self , earlier : Self ) -> Duration ;
21- }
22-
23- /// A state in which time has no meaning.
24- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
25- pub struct Eternity ;
26-
27- impl Time for Eternity {
28- fn now ( ) -> Self {
29- Self
30- }
31-
32- fn duration_since ( & self , _earlier : Self ) -> Duration {
33- Duration :: from_secs ( 0 )
34- }
35- }
36-
37- impl Sub < Duration > for Eternity {
38- type Output = Self ;
39-
40- fn sub ( self , _other : Duration ) -> Self {
41- self
42- }
43- }
44-
45- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
46- #[ cfg( feature = "std" ) ]
47- pub struct MonotonicTime ( std:: time:: Instant ) ;
48-
49- /// The amount of time to shift `Instant` forward to prevent overflow when subtracting a `Duration`
50- /// from `Instant::now` on some operating systems (e.g., iOS representing `Instance` as `u64`).
51- #[ cfg( feature = "std" ) ]
52- const SHIFT : Duration = Duration :: from_secs ( 10 * 365 * 24 * 60 * 60 ) ; // 10 years.
53-
54- #[ cfg( feature = "std" ) ]
55- impl Time for MonotonicTime {
56- fn now ( ) -> Self {
57- let instant = std:: time:: Instant :: now ( ) . checked_add ( SHIFT ) . expect ( "Overflow on MonotonicTime instantiation" ) ;
58- Self ( instant)
59- }
60-
61- fn duration_since ( & self , earlier : Self ) -> Duration {
62- // On rust prior to 1.60 `Instant::duration_since` will panic if time goes backwards.
63- // However, we support rust versions prior to 1.60 and some users appear to have "monotonic
64- // clocks" that go backwards in practice (likely relatively ancient kernels/etc). Thus, we
65- // manually check for time going backwards here and return a duration of zero in that case.
66- let now = Self :: now ( ) ;
67- if now. 0 > earlier. 0 { now. 0 - earlier. 0 } else { Duration :: from_secs ( 0 ) }
68- }
69- }
70-
71- #[ cfg( feature = "std" ) ]
72- impl Sub < Duration > for MonotonicTime {
73- type Output = Self ;
74-
75- fn sub ( self , other : Duration ) -> Self {
76- let instant = self . 0 . checked_sub ( other) . expect ( "MonotonicTime is not supposed to go backward futher than 10 years" ) ;
77- Self ( instant)
78- }
79- }
7+ //! A simple module which either re-exports [`std::time::Instant`] or a mocked version of it for
8+ //! tests.
809
8110#[ cfg( test) ]
82- pub mod tests {
83- use super :: { Time , Eternity } ;
11+ pub use test:: Instant ;
12+ #[ cfg( not( test) ) ]
13+ pub use std:: time:: Instant ;
8414
15+ #[ cfg( test) ]
16+ mod test {
8517 use core:: time:: Duration ;
8618 use core:: ops:: Sub ;
8719 use core:: cell:: Cell ;
8820
8921 /// Time that can be advanced manually in tests.
9022 #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
91- pub struct SinceEpoch ( Duration ) ;
23+ pub struct Instant ( Duration ) ;
9224
93- impl SinceEpoch {
25+ impl Instant {
9426 thread_local ! {
9527 static ELAPSED : Cell <Duration > = core:: cell:: Cell :: new( Duration :: from_secs( 0 ) ) ;
9628 }
9729
9830 pub fn advance ( duration : Duration ) {
9931 Self :: ELAPSED . with ( |elapsed| elapsed. set ( elapsed. get ( ) + duration) )
10032 }
101- }
10233
103- impl Time for SinceEpoch {
104- fn now ( ) -> Self {
34+ pub fn now ( ) -> Self {
10535 Self ( Self :: ELAPSED . with ( |elapsed| elapsed. get ( ) ) )
10636 }
10737
108- fn duration_since ( & self , earlier : Self ) -> Duration {
38+ pub fn duration_since ( & self , earlier : Self ) -> Duration {
10939 self . 0 - earlier. 0
11040 }
11141 }
11242
113- impl Sub < Duration > for SinceEpoch {
43+ impl Sub < Duration > for Instant {
11444 type Output = Self ;
11545
11646 fn sub ( self , other : Duration ) -> Self {
@@ -120,21 +50,13 @@ pub mod tests {
12050
12151 #[ test]
12252 fn time_passes_when_advanced ( ) {
123- let now = SinceEpoch :: now ( ) ;
53+ let now = Instant :: now ( ) ;
12454
125- SinceEpoch :: advance ( Duration :: from_secs ( 1 ) ) ;
126- SinceEpoch :: advance ( Duration :: from_secs ( 1 ) ) ;
55+ Instant :: advance ( Duration :: from_secs ( 1 ) ) ;
56+ Instant :: advance ( Duration :: from_secs ( 1 ) ) ;
12757
128- let later = SinceEpoch :: now ( ) ;
58+ let later = Instant :: now ( ) ;
12959
13060 assert_eq ! ( now. 0 + Duration :: from_secs( 2 ) , later. 0 ) ;
13161 }
132-
133- #[ test]
134- fn time_never_passes_in_an_eternity ( ) {
135- let now = Eternity :: now ( ) ;
136- let later = Eternity :: now ( ) ;
137-
138- assert_eq ! ( later, now) ;
139- }
14062}
0 commit comments