1
- use crate :: cmp:: Ordering ;
2
1
use crate :: time:: Duration ;
3
2
4
- use core:: hash:: { Hash , Hasher } ;
5
-
6
3
pub use self :: inner:: { Instant , SystemTime , UNIX_EPOCH } ;
7
4
use crate :: convert:: TryInto ;
8
5
9
6
const NSEC_PER_SEC : u64 = 1_000_000_000 ;
10
7
11
- #[ derive( Copy , Clone ) ]
8
+ #[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
12
9
pub ( in crate :: sys:: unix) struct Timespec {
13
- pub t : libc:: timespec ,
10
+ tv_sec : i64 ,
11
+ tv_nsec : i64 ,
14
12
}
15
13
16
14
impl Timespec {
17
15
const fn zero ( ) -> Timespec {
18
- Timespec { t : libc:: timespec { tv_sec : 0 , tv_nsec : 0 } }
16
+ Timespec { tv_sec : 0 , tv_nsec : 0 }
17
+ }
18
+
19
+ fn new ( tv_sec : i64 , tv_nsec : i64 ) -> Timespec {
20
+ Timespec { tv_sec, tv_nsec }
19
21
}
20
22
21
23
pub fn sub_timespec ( & self , other : & Timespec ) -> Result < Duration , Duration > {
22
24
if self >= other {
23
25
// NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
24
26
// to optimize it into a branchless form (see also #75545):
25
27
//
26
- // 1. `self.t. tv_sec - other.t .tv_sec` shows up as a common expression
28
+ // 1. `self.tv_sec - other.tv_sec` shows up as a common expression
27
29
// in both branches, i.e. the `else` must have its `- 1`
28
30
// subtraction after the common one, not interleaved with it
29
- // (it used to be `self.t. tv_sec - 1 - other.t .tv_sec`)
31
+ // (it used to be `self.tv_sec - 1 - other.tv_sec`)
30
32
//
31
33
// 2. the `Duration::new` call (or any other additional complexity)
32
34
// is outside of the `if`-`else`, not duplicated in both branches
33
35
//
34
36
// Ideally this code could be rearranged such that it more
35
37
// directly expresses the lower-cost behavior we want from it.
36
- let ( secs, nsec) = if self . t . tv_nsec >= other. t . tv_nsec {
37
- ( ( self . t . tv_sec - other. t . tv_sec ) as u64 , ( self . t . tv_nsec - other. t . tv_nsec ) as u32 )
38
+ let ( secs, nsec) = if self . tv_nsec >= other. tv_nsec {
39
+ ( ( self . tv_sec - other. tv_sec ) as u64 , ( self . tv_nsec - other. tv_nsec ) as u32 )
38
40
} else {
39
41
(
40
- ( self . t . tv_sec - other. t . tv_sec - 1 ) as u64 ,
41
- self . t . tv_nsec as u32 + ( NSEC_PER_SEC as u32 ) - other. t . tv_nsec as u32 ,
42
+ ( self . tv_sec - other. tv_sec - 1 ) as u64 ,
43
+ self . tv_nsec as u32 + ( NSEC_PER_SEC as u32 ) - other. tv_nsec as u32 ,
42
44
)
43
45
} ;
44
46
@@ -54,63 +56,34 @@ impl Timespec {
54
56
pub fn checked_add_duration ( & self , other : & Duration ) -> Option < Timespec > {
55
57
let mut secs = other
56
58
. as_secs ( )
57
- . try_into ( ) // <- target type would be `libc::time_t `
59
+ . try_into ( ) // <- target type would be `i64 `
58
60
. ok ( )
59
- . and_then ( |secs| self . t . tv_sec . checked_add ( secs) ) ?;
61
+ . and_then ( |secs| self . tv_sec . checked_add ( secs) ) ?;
60
62
61
63
// Nano calculations can't overflow because nanos are <1B which fit
62
64
// in a u32.
63
- let mut nsec = other. subsec_nanos ( ) + self . t . tv_nsec as u32 ;
65
+ let mut nsec = other. subsec_nanos ( ) + self . tv_nsec as u32 ;
64
66
if nsec >= NSEC_PER_SEC as u32 {
65
67
nsec -= NSEC_PER_SEC as u32 ;
66
68
secs = secs. checked_add ( 1 ) ?;
67
69
}
68
- Some ( Timespec { t : libc :: timespec { tv_sec : secs, tv_nsec : nsec as _ } } )
70
+ Some ( Timespec :: new ( secs, nsec as i64 ) )
69
71
}
70
72
71
73
pub fn checked_sub_duration ( & self , other : & Duration ) -> Option < Timespec > {
72
74
let mut secs = other
73
75
. as_secs ( )
74
- . try_into ( ) // <- target type would be `libc::time_t `
76
+ . try_into ( ) // <- target type would be `i64 `
75
77
. ok ( )
76
- . and_then ( |secs| self . t . tv_sec . checked_sub ( secs) ) ?;
78
+ . and_then ( |secs| self . tv_sec . checked_sub ( secs) ) ?;
77
79
78
80
// Similar to above, nanos can't overflow.
79
- let mut nsec = self . t . tv_nsec as i32 - other. subsec_nanos ( ) as i32 ;
81
+ let mut nsec = self . tv_nsec as i32 - other. subsec_nanos ( ) as i32 ;
80
82
if nsec < 0 {
81
83
nsec += NSEC_PER_SEC as i32 ;
82
84
secs = secs. checked_sub ( 1 ) ?;
83
85
}
84
- Some ( Timespec { t : libc:: timespec { tv_sec : secs, tv_nsec : nsec as _ } } )
85
- }
86
- }
87
-
88
- impl PartialEq for Timespec {
89
- fn eq ( & self , other : & Timespec ) -> bool {
90
- self . t . tv_sec == other. t . tv_sec && self . t . tv_nsec == other. t . tv_nsec
91
- }
92
- }
93
-
94
- impl Eq for Timespec { }
95
-
96
- impl PartialOrd for Timespec {
97
- fn partial_cmp ( & self , other : & Timespec ) -> Option < Ordering > {
98
- Some ( self . cmp ( other) )
99
- }
100
- }
101
-
102
- impl Ord for Timespec {
103
- fn cmp ( & self , other : & Timespec ) -> Ordering {
104
- let me = ( self . t . tv_sec , self . t . tv_nsec ) ;
105
- let other = ( other. t . tv_sec , other. t . tv_nsec ) ;
106
- me. cmp ( & other)
107
- }
108
- }
109
-
110
- impl Hash for Timespec {
111
- fn hash < H : Hasher > ( & self , state : & mut H ) {
112
- self . t . tv_sec . hash ( state) ;
113
- self . t . tv_nsec . hash ( state) ;
86
+ Some ( Timespec :: new ( secs, nsec as i64 ) )
114
87
}
115
88
}
116
89
@@ -192,26 +165,35 @@ mod inner {
192
165
}
193
166
}
194
167
168
+ impl From < libc:: timeval > for Timespec {
169
+ fn from ( t : libc:: timeval ) -> Timespec {
170
+ Timespec :: new ( t. tv_sec as i64 , 1000 * t. tv_usec as i64 )
171
+ }
172
+ }
173
+
195
174
impl From < libc:: timeval > for SystemTime {
196
175
fn from ( t : libc:: timeval ) -> SystemTime {
197
- SystemTime :: from ( libc:: timespec {
198
- tv_sec : t. tv_sec ,
199
- tv_nsec : ( t. tv_usec * 1000 ) as libc:: c_long ,
200
- } )
176
+ SystemTime { t : Timespec :: from ( t) }
177
+ }
178
+ }
179
+
180
+ impl From < libc:: timespec > for Timespec {
181
+ fn from ( t : libc:: timespec ) -> Timespec {
182
+ Timespec :: new ( t. tv_sec as i64 , t. tv_nsec as i64 )
201
183
}
202
184
}
203
185
204
186
impl From < libc:: timespec > for SystemTime {
205
187
fn from ( t : libc:: timespec ) -> SystemTime {
206
- SystemTime { t : Timespec { t } }
188
+ SystemTime { t : Timespec :: from ( t ) }
207
189
}
208
190
}
209
191
210
192
impl fmt:: Debug for SystemTime {
211
193
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
212
194
f. debug_struct ( "SystemTime" )
213
- . field ( "tv_sec" , & self . t . t . tv_sec )
214
- . field ( "tv_nsec" , & self . t . t . tv_nsec )
195
+ . field ( "tv_sec" , & self . t . tv_sec )
196
+ . field ( "tv_nsec" , & self . t . tv_nsec )
215
197
. finish ( )
216
198
}
217
199
}
@@ -305,8 +287,8 @@ mod inner {
305
287
impl fmt:: Debug for Instant {
306
288
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
307
289
f. debug_struct ( "Instant" )
308
- . field ( "tv_sec" , & self . t . t . tv_sec )
309
- . field ( "tv_nsec" , & self . t . t . tv_nsec )
290
+ . field ( "tv_sec" , & self . t . tv_sec )
291
+ . field ( "tv_nsec" , & self . t . tv_nsec )
310
292
. finish ( )
311
293
}
312
294
}
@@ -329,17 +311,23 @@ mod inner {
329
311
}
330
312
}
331
313
314
+ impl From < libc:: timespec > for Timespec {
315
+ fn from ( t : libc:: timespec ) -> Timespec {
316
+ Timespec :: new ( t. tv_sec as i64 , t. tv_nsec as i64 )
317
+ }
318
+ }
319
+
332
320
impl From < libc:: timespec > for SystemTime {
333
321
fn from ( t : libc:: timespec ) -> SystemTime {
334
- SystemTime { t : Timespec { t } }
322
+ SystemTime { t : Timespec :: from ( t ) }
335
323
}
336
324
}
337
325
338
326
impl fmt:: Debug for SystemTime {
339
327
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
340
328
f. debug_struct ( "SystemTime" )
341
- . field ( "tv_sec" , & self . t . t . tv_sec )
342
- . field ( "tv_nsec" , & self . t . t . tv_nsec )
329
+ . field ( "tv_sec" , & self . t . tv_sec )
330
+ . field ( "tv_nsec" , & self . t . tv_nsec )
343
331
. finish ( )
344
332
}
345
333
}
@@ -353,7 +341,15 @@ mod inner {
353
341
pub fn now ( clock : clock_t ) -> Timespec {
354
342
let mut t = MaybeUninit :: uninit ( ) ;
355
343
cvt ( unsafe { libc:: clock_gettime ( clock, t. as_mut_ptr ( ) ) } ) . unwrap ( ) ;
356
- Timespec { t : unsafe { t. assume_init ( ) } }
344
+ Timespec :: from ( unsafe { t. assume_init ( ) } )
345
+ }
346
+
347
+ pub fn to_timespec ( & self ) -> Option < libc:: timespec > {
348
+ use crate :: convert:: TryInto ;
349
+ Some ( libc:: timespec {
350
+ tv_sec : self . tv_sec . try_into ( ) . ok ( ) ?,
351
+ tv_nsec : self . tv_nsec . try_into ( ) . ok ( ) ?,
352
+ } )
357
353
}
358
354
}
359
355
}
0 commit comments