Skip to content

Commit 13f0463

Browse files
committed
Add checked_add method to Instant time type
1 parent 9fe5cb5 commit 13f0463

File tree

6 files changed

+62
-74
lines changed

6 files changed

+62
-74
lines changed

src/libstd/sys/cloudabi/time.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub struct Instant {
2121

2222
fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
2323
dur.as_secs()
24-
.checked_mul(NSEC_PER_SEC)
25-
.and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
24+
.checked_mul(NSEC_PER_SEC)?
25+
.checked_add(dur.subsec_nanos() as abi::timestamp)
2626
}
2727

2828
pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
@@ -47,12 +47,10 @@ impl Instant {
4747
Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
4848
}
4949

50-
pub fn add_duration(&self, other: &Duration) -> Instant {
51-
Instant {
52-
t: self.t
53-
.checked_add(dur2intervals(other))
54-
.expect("overflow when adding duration to instant"),
55-
}
50+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
51+
checked_dur2intervals(other)?
52+
.checked_add(self.t)
53+
.map(|t| Instant {t})
5654
}
5755

5856
pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -95,11 +93,6 @@ impl SystemTime {
9593
}
9694
}
9795

98-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
99-
self.checked_add_duration(other)
100-
.expect("overflow when adding duration to instant")
101-
}
102-
10396
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
10497
checked_dur2intervals(other)
10598
.and_then(|d| self.t.checked_add(d))

src/libstd/sys/redox/time.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ impl Timespec {
4141
}
4242
}
4343

44-
fn add_duration(&self, other: &Duration) -> Timespec {
45-
self.checked_add_duration(other).expect("overflow when adding duration to time")
46-
}
47-
4844
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
4945
let mut secs = other
5046
.as_secs()
@@ -150,8 +146,8 @@ impl Instant {
150146
})
151147
}
152148

153-
pub fn add_duration(&self, other: &Duration) -> Instant {
154-
Instant { t: self.t.add_duration(other) }
149+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
150+
self.t.checked_add_duration(other).map(|t| Instant { t })
155151
}
156152

157153
pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -178,10 +174,6 @@ impl SystemTime {
178174
self.t.sub_timespec(&other.t)
179175
}
180176

181-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
182-
SystemTime { t: self.t.add_duration(other) }
183-
}
184-
185177
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
186178
self.t.checked_add_duration(other).map(|t| SystemTime { t })
187179
}

src/libstd/sys/unix/time.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ impl Timespec {
4242
}
4343
}
4444

45-
fn add_duration(&self, other: &Duration) -> Timespec {
46-
self.checked_add_duration(other).expect("overflow when adding duration to time")
47-
}
48-
4945
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
5046
let mut secs = other
5147
.as_secs()
@@ -165,11 +161,8 @@ mod inner {
165161
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
166162
}
167163

168-
pub fn add_duration(&self, other: &Duration) -> Instant {
169-
Instant {
170-
t: self.t.checked_add(dur2intervals(other))
171-
.expect("overflow when adding duration to instant"),
172-
}
164+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
165+
checked_dur2intervals(other)?.checked_add(self.t).map(|t| Instant {t})
173166
}
174167

175168
pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -199,10 +192,6 @@ mod inner {
199192
self.t.sub_timespec(&other.t)
200193
}
201194

202-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
203-
SystemTime { t: self.t.add_duration(other) }
204-
}
205-
206195
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
207196
self.t.checked_add_duration(other).map(|t| SystemTime { t })
208197
}
@@ -237,11 +226,16 @@ mod inner {
237226
}
238227

239228
fn dur2intervals(dur: &Duration) -> u64 {
229+
checked_dur2intervals(dur)
230+
.expect("overflow converting duration to nanoseconds")
231+
}
232+
233+
fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
234+
let nanos = dur.as_secs()
235+
.checked_mul(NSEC_PER_SEC)?
236+
.checked_add(dur.subsec_nanos() as u64)?;
240237
let info = info();
241-
let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
242-
nanos.checked_add(dur.subsec_nanos() as u64)
243-
}).expect("overflow converting duration to nanoseconds");
244-
mul_div_u64(nanos, info.denom as u64, info.numer as u64)
238+
Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
245239
}
246240

247241
fn info() -> &'static libc::mach_timebase_info {
@@ -299,8 +293,8 @@ mod inner {
299293
})
300294
}
301295

302-
pub fn add_duration(&self, other: &Duration) -> Instant {
303-
Instant { t: self.t.add_duration(other) }
296+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
297+
self.t.checked_add_duration(other).map(|t| Instant { t })
304298
}
305299

306300
pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -327,10 +321,6 @@ mod inner {
327321
self.t.sub_timespec(&other.t)
328322
}
329323

330-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
331-
SystemTime { t: self.t.add_duration(other) }
332-
}
333-
334324
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
335325
self.t.checked_add_duration(other).map(|t| SystemTime { t })
336326
}

src/libstd/sys/wasm/time.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl Instant {
2828
self.0 - other.0
2929
}
3030

31-
pub fn add_duration(&self, other: &Duration) -> Instant {
32-
Instant(self.0 + *other)
31+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
32+
self.0.checked_add(*other).map(|d| Instant(d))
3333
}
3434

3535
pub fn sub_duration(&self, other: &Duration) -> Instant {
@@ -47,10 +47,6 @@ impl SystemTime {
4747
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
4848
}
4949

50-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
51-
SystemTime(self.0 + *other)
52-
}
53-
5450
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
5551
self.0.checked_add(*other).map(|d| SystemTime(d))
5652
}

src/libstd/sys/windows/time.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,26 +68,23 @@ impl Instant {
6868
Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
6969
}
7070

71-
pub fn add_duration(&self, other: &Duration) -> Instant {
71+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
7272
let freq = frequency() as u64;
73-
let t = other.as_secs().checked_mul(freq).and_then(|i| {
74-
(self.t as u64).checked_add(i)
75-
}).and_then(|i| {
76-
i.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq,
77-
NANOS_PER_SEC))
78-
}).expect("overflow when adding duration to time");
79-
Instant {
73+
let t = other.as_secs()
74+
.checked_mul(freq)?
75+
.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))?
76+
.checked_add(self.t as u64)?;
77+
Some(Instant {
8078
t: t as c::LARGE_INTEGER,
81-
}
79+
})
8280
}
8381

8482
pub fn sub_duration(&self, other: &Duration) -> Instant {
8583
let freq = frequency() as u64;
8684
let t = other.as_secs().checked_mul(freq).and_then(|i| {
8785
(self.t as u64).checked_sub(i)
8886
}).and_then(|i| {
89-
i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq,
90-
NANOS_PER_SEC))
87+
i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))
9188
}).expect("overflow when subtracting duration from time");
9289
Instant {
9390
t: t as c::LARGE_INTEGER,
@@ -127,10 +124,6 @@ impl SystemTime {
127124
}
128125
}
129126

130-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
131-
self.checked_add_duration(other).expect("overflow when adding duration to time")
132-
}
133-
134127
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
135128
checked_dur2intervals(other)
136129
.and_then(|d| self.intervals().checked_add(d))
@@ -184,11 +177,12 @@ impl Hash for SystemTime {
184177
}
185178
}
186179

187-
fn checked_dur2intervals(d: &Duration) -> Option<i64> {
188-
d.as_secs()
189-
.checked_mul(INTERVALS_PER_SEC)
190-
.and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100))
191-
.and_then(|i| i.try_into().ok())
180+
fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
181+
dur.as_secs()
182+
.checked_mul(INTERVALS_PER_SEC)?
183+
.checked_add(dur.subsec_nanos() as u64 / 100)?
184+
.try_into()
185+
.ok()
192186
}
193187

194188
fn dur2intervals(d: &Duration) -> i64 {

src/libstd/time.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,23 @@ impl Instant {
208208
pub fn elapsed(&self) -> Duration {
209209
Instant::now() - *self
210210
}
211+
212+
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
213+
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
214+
/// otherwise.
215+
#[unstable(feature = "time_checked_add", issue = "55940")]
216+
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
217+
self.0.checked_add_duration(&duration).map(|t| Instant(t))
218+
}
211219
}
212220

213221
#[stable(feature = "time2", since = "1.8.0")]
214222
impl Add<Duration> for Instant {
215223
type Output = Instant;
216224

217225
fn add(self, other: Duration) -> Instant {
218-
Instant(self.0.add_duration(&other))
226+
self.checked_add(other)
227+
.expect("overflow when adding duration to instant")
219228
}
220229
}
221230

@@ -372,7 +381,8 @@ impl Add<Duration> for SystemTime {
372381
type Output = SystemTime;
373382

374383
fn add(self, dur: Duration) -> SystemTime {
375-
SystemTime(self.0.add_duration(&dur))
384+
self.checked_add(dur)
385+
.expect("overflow when adding duration to instant")
376386
}
377387
}
378388

@@ -521,6 +531,19 @@ mod tests {
521531

522532
let second = Duration::new(1, 0);
523533
assert_almost_eq!(a - second + second, a);
534+
535+
// checked_add_duration will not panic on overflow
536+
let mut maybe_t = Some(Instant::now());
537+
let max_duration = Duration::from_secs(u64::max_value());
538+
// in case `Instant` can store `>= now + max_duration`.
539+
for _ in 0..2 {
540+
maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
541+
}
542+
assert_eq!(maybe_t, None);
543+
544+
// checked_add_duration calculates the right time and will work for another year
545+
let year = Duration::from_secs(60 * 60 * 24 * 365);
546+
assert_eq!(a + year, a.checked_add(year).unwrap());
524547
}
525548

526549
#[test]

0 commit comments

Comments
 (0)