@@ -2,6 +2,7 @@ use std::{
2
2
io:: { Read , Write } ,
3
3
mem:: MaybeUninit ,
4
4
ops:: { Add , Sub } ,
5
+ time:: Duration ,
5
6
} ;
6
7
7
8
/// A timestamp relative to `CLOCK_BOOTTIME`.
@@ -51,85 +52,47 @@ impl SystemTime {
51
52
i64:: from_ne_bytes ( nsec_bytes) ,
52
53
) )
53
54
}
54
- }
55
-
56
- impl Sub < SystemTime > for SystemTime {
57
- type Output = Duration ;
58
-
59
- fn sub ( self , rhs : SystemTime ) -> Self :: Output {
60
- Duration :: new ( self . secs - rhs. secs , self . nsecs - rhs. nsecs )
61
- }
62
- }
63
-
64
- impl Add < Duration > for SystemTime {
65
- type Output = SystemTime ;
66
-
67
- fn add ( self , rhs : Duration ) -> Self :: Output {
68
- SystemTime :: new ( self . secs + rhs. secs , self . nsecs + rhs. nsecs )
69
- }
70
- }
71
-
72
- impl Sub < Duration > for SystemTime {
73
- type Output = SystemTime ;
74
55
75
- fn sub ( self , rhs : Duration ) -> Self :: Output {
76
- SystemTime :: new ( self . secs - rhs. secs , self . nsecs - rhs . nsecs )
77
- }
78
- }
56
+ # [ inline ]
57
+ pub fn checked_add ( self , rhs : Duration ) -> Option < SystemTime > {
58
+ let rhs_secs = rhs . as_nanos ( ) . div_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ? ;
59
+ let rhs_nsecs = rhs . as_nanos ( ) . rem_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ? ;
79
60
80
- #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord , Clone , Copy ) ]
81
- pub struct Duration {
82
- secs : i64 ,
83
- nsecs : i64 ,
84
- }
61
+ let secs = self . secs . checked_add ( rhs_secs) ?;
62
+ let nsecs = self . nsecs . checked_add ( rhs_nsecs) ?;
85
63
86
- impl Duration {
87
- pub fn new ( secs : i64 , nsecs : i64 ) -> Duration {
88
- Duration {
89
- secs : secs + nsecs. div_euclid ( 1_000_000_000 ) ,
90
- nsecs : nsecs. rem_euclid ( 1_000_000_000 ) ,
91
- }
64
+ Some ( SystemTime :: new ( secs, nsecs) )
92
65
}
93
66
94
- pub fn seconds ( secs : i64 ) -> Duration {
95
- Duration :: new ( secs, 0 )
96
- }
67
+ #[ inline]
68
+ pub fn checked_sub ( self , rhs : Duration ) -> Option < SystemTime > {
69
+ let rhs_secs = rhs. as_nanos ( ) . div_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ?;
70
+ let rhs_nsecs = rhs. as_nanos ( ) . rem_euclid ( 1_000_000_000 ) . try_into ( ) . ok ( ) ?;
97
71
98
- #[ cfg( test) ]
99
- pub fn minutes ( minutes : i64 ) -> Duration {
100
- Duration :: seconds ( minutes * 60 )
101
- }
72
+ let secs = self . secs . checked_sub ( rhs_secs) ?;
73
+ let nsecs = self . nsecs . checked_sub ( rhs_nsecs) ?;
102
74
103
- #[ cfg( test) ]
104
- pub fn milliseconds ( ms : i64 ) -> Duration {
105
- let secs = ms / 1000 ;
106
- let ms = ms % 1000 ;
107
- Duration :: new ( secs, ms * 1_000_000 )
75
+ Some ( SystemTime :: new ( secs, nsecs) )
108
76
}
109
77
}
110
78
111
- impl Add < Duration > for Duration {
112
- type Output = Duration ;
79
+ impl Add < Duration > for SystemTime {
80
+ type Output = SystemTime ;
113
81
82
+ #[ inline]
114
83
fn add ( self , rhs : Duration ) -> Self :: Output {
115
- Duration :: new ( self . secs + rhs. secs , self . nsecs + rhs. nsecs )
84
+ self . checked_add ( rhs)
85
+ . expect ( "overflow when adding duration" )
116
86
}
117
87
}
118
88
119
- impl Sub < Duration > for Duration {
120
- type Output = Duration ;
89
+ impl Sub < Duration > for SystemTime {
90
+ type Output = SystemTime ;
121
91
92
+ #[ inline]
122
93
fn sub ( self , rhs : Duration ) -> Self :: Output {
123
- Duration :: new ( self . secs - rhs. secs , self . nsecs - rhs. nsecs )
124
- }
125
- }
126
-
127
- impl From < Duration > for std:: time:: Duration {
128
- fn from ( dur : Duration ) -> std:: time:: Duration {
129
- std:: time:: Duration :: new (
130
- dur. secs . try_into ( ) . unwrap_or ( 0 ) ,
131
- dur. nsecs . try_into ( ) . unwrap_or ( 0 ) ,
132
- )
94
+ self . checked_sub ( rhs)
95
+ . expect ( "overflow when subtracting duration" )
133
96
}
134
97
}
135
98
@@ -213,13 +176,7 @@ mod tests {
213
176
use super :: * ;
214
177
215
178
#[ test]
216
- fn test_new_durations_and_times ( ) {
217
- assert_eq ! ( Duration :: new( 1 , 1_000_000_000 ) , Duration :: seconds( 2 ) ) ;
218
- assert_eq ! (
219
- Duration :: new( -2 , 500_000_000 ) ,
220
- Duration :: seconds( -1 ) + Duration :: milliseconds( -500 )
221
- ) ;
222
-
179
+ fn test_new_system_time ( ) {
223
180
assert_eq ! ( SystemTime :: new( -1 , 2_000_000_000 ) , SystemTime :: new( 1 , 0 ) ) ;
224
181
assert_eq ! (
225
182
SystemTime :: new( 2 , -500_000_000 ) ,
@@ -230,37 +187,20 @@ mod tests {
230
187
#[ test]
231
188
fn test_time_ops ( ) {
232
189
assert_eq ! (
233
- Duration :: seconds( 2 ) + Duration :: seconds( 3 ) ,
234
- Duration :: seconds( 5 )
235
- ) ;
236
- assert_eq ! (
237
- Duration :: seconds( 3 ) - Duration :: seconds( 1 ) ,
238
- Duration :: seconds( 2 )
239
- ) ;
240
- assert_eq ! (
241
- Duration :: seconds( -10 ) + Duration :: seconds( -5 ) ,
242
- Duration :: seconds( -15 )
243
- ) ;
244
- assert_eq ! (
245
- Duration :: milliseconds( 5555 ) + Duration :: milliseconds( 5555 ) ,
246
- Duration :: seconds( 11 ) + Duration :: milliseconds( 110 )
247
- ) ;
248
- assert_eq ! (
249
- Duration :: milliseconds( -5555 ) + Duration :: milliseconds( -1111 ) ,
250
- Duration :: milliseconds( -6666 )
251
- ) ;
252
- assert_eq ! (
253
- Duration :: seconds( 10 ) - Duration :: seconds( -5 ) ,
254
- Duration :: seconds( 15 )
190
+ SystemTime :: new( 0 , 0 ) + Duration :: from_secs( 3 ) ,
191
+ SystemTime :: new( 3 , 0 )
255
192
) ;
256
-
257
193
assert_eq ! (
258
- SystemTime :: new( 0 , 0 ) + Duration :: seconds ( 3 ) ,
194
+ SystemTime :: new( 0 , 500_000_000 ) + Duration :: from_nanos ( 2_500_000_000 ) ,
259
195
SystemTime :: new( 3 , 0 )
260
196
) ;
261
197
assert_eq ! (
262
- SystemTime :: new( 10 , 0 ) - Duration :: seconds ( 4 ) ,
198
+ SystemTime :: new( 10 , 0 ) - Duration :: from_secs ( 4 ) ,
263
199
SystemTime :: new( 6 , 0 )
264
200
) ;
201
+ assert_eq ! (
202
+ SystemTime :: new( 10 , 0 ) - Duration :: from_nanos( 3_500_000_000 ) ,
203
+ SystemTime :: new( 6 , 500_000_000 )
204
+ ) ;
265
205
}
266
206
}
0 commit comments