Auto merge of #56490 - faern:add-checked-add-to-instant, r=alexcrichton
Add checked_add method to Instant time type Appending functionality to the already opened topic of `checked_add` on time types over at #55940. Doing checked addition between an `Instant` and a `Duration` is important to reliably determine a future instant. We could use this in the `parking_lot` crate to compute an instant when in the future to wake a thread up without risking a panic.
This commit is contained in:
commit
f4b07e0713
@ -13,7 +13,7 @@ use mem;
|
||||
use sync::atomic::{AtomicU32, Ordering};
|
||||
use sys::cloudabi::abi;
|
||||
use sys::mutex::{self, Mutex};
|
||||
use sys::time::dur2intervals;
|
||||
use sys::time::checked_dur2intervals;
|
||||
use time::Duration;
|
||||
|
||||
extern "C" {
|
||||
@ -114,6 +114,8 @@ impl Condvar {
|
||||
|
||||
// Call into the kernel to wait on the condition variable.
|
||||
let condvar = self.condvar.get();
|
||||
let timeout = checked_dur2intervals(&dur)
|
||||
.expect("overflow converting duration to nanoseconds");
|
||||
let subscriptions = [
|
||||
abi::subscription {
|
||||
type_: abi::eventtype::CONDVAR,
|
||||
@ -132,7 +134,7 @@ impl Condvar {
|
||||
union: abi::subscription_union {
|
||||
clock: abi::subscription_clock {
|
||||
clock_id: abi::clockid::MONOTONIC,
|
||||
timeout: dur2intervals(&dur),
|
||||
timeout,
|
||||
..mem::zeroed()
|
||||
},
|
||||
},
|
||||
|
@ -16,7 +16,7 @@ use libc;
|
||||
use mem;
|
||||
use ptr;
|
||||
use sys::cloudabi::abi;
|
||||
use sys::time::dur2intervals;
|
||||
use sys::time::checked_dur2intervals;
|
||||
use sys_common::thread::*;
|
||||
use time::Duration;
|
||||
|
||||
@ -70,13 +70,15 @@ impl Thread {
|
||||
}
|
||||
|
||||
pub fn sleep(dur: Duration) {
|
||||
let timeout = checked_dur2intervals(&dur)
|
||||
.expect("overflow converting duration to nanoseconds");
|
||||
unsafe {
|
||||
let subscription = abi::subscription {
|
||||
type_: abi::eventtype::CLOCK,
|
||||
union: abi::subscription_union {
|
||||
clock: abi::subscription_clock {
|
||||
clock_id: abi::clockid::MONOTONIC,
|
||||
timeout: dur2intervals(&dur),
|
||||
timeout,
|
||||
..mem::zeroed()
|
||||
},
|
||||
},
|
||||
|
@ -19,15 +19,10 @@ pub struct Instant {
|
||||
t: abi::timestamp,
|
||||
}
|
||||
|
||||
fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
|
||||
pub fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
|
||||
dur.as_secs()
|
||||
.checked_mul(NSEC_PER_SEC)
|
||||
.and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
|
||||
}
|
||||
|
||||
pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
|
||||
checked_dur2intervals(dur)
|
||||
.expect("overflow converting duration to nanoseconds")
|
||||
.checked_mul(NSEC_PER_SEC)?
|
||||
.checked_add(dur.subsec_nanos() as abi::timestamp)
|
||||
}
|
||||
|
||||
impl Instant {
|
||||
@ -47,20 +42,16 @@ impl Instant {
|
||||
Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant {
|
||||
t: self.t
|
||||
.checked_add(dur2intervals(other))
|
||||
.expect("overflow when adding duration to instant"),
|
||||
}
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant {
|
||||
t: self.t.checked_add(checked_dur2intervals(other)?)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
Instant {
|
||||
t: self.t
|
||||
.checked_sub(dur2intervals(other))
|
||||
.expect("overflow when subtracting duration from instant"),
|
||||
}
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant {
|
||||
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,23 +86,16 @@ impl SystemTime {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
self.checked_add_duration(other)
|
||||
.expect("overflow when adding duration to instant")
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
checked_dur2intervals(other)
|
||||
.and_then(|d| self.t.checked_add(d))
|
||||
.map(|t| SystemTime {t})
|
||||
Some(SystemTime {
|
||||
t: self.t.checked_add(checked_dur2intervals(other)?)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime {
|
||||
t: self.t
|
||||
.checked_sub(dur2intervals(other))
|
||||
.expect("overflow when subtracting duration from instant"),
|
||||
}
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime {
|
||||
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,10 +41,6 @@ impl Timespec {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_duration(&self, other: &Duration) -> Timespec {
|
||||
self.checked_add_duration(other).expect("overflow when adding duration to time")
|
||||
}
|
||||
|
||||
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = other
|
||||
.as_secs()
|
||||
@ -67,27 +63,25 @@ impl Timespec {
|
||||
})
|
||||
}
|
||||
|
||||
fn sub_duration(&self, other: &Duration) -> Timespec {
|
||||
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = other
|
||||
.as_secs()
|
||||
.try_into() // <- target type would be `i64`
|
||||
.ok()
|
||||
.and_then(|secs| self.t.tv_sec.checked_sub(secs))
|
||||
.expect("overflow when subtracting duration from time");
|
||||
.and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
|
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
|
||||
if nsec < 0 {
|
||||
nsec += NSEC_PER_SEC as i32;
|
||||
secs = secs.checked_sub(1).expect("overflow when subtracting \
|
||||
duration from time");
|
||||
secs = secs.checked_sub(1)?;
|
||||
}
|
||||
Timespec {
|
||||
Some(Timespec {
|
||||
t: syscall::TimeSpec {
|
||||
tv_sec: secs,
|
||||
tv_nsec: nsec as i32,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,12 +144,12 @@ impl Instant {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant { t: self.t.add_duration(other) }
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
Instant { t: self.t.sub_duration(other) }
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,16 +172,12 @@ impl SystemTime {
|
||||
self.t.sub_timespec(&other.t)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime { t: self.t.add_duration(other) }
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
self.t.checked_add_duration(other).map(|t| SystemTime { t })
|
||||
Some(SystemTime { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime { t: self.t.sub_duration(other) }
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,12 +28,12 @@ impl Instant {
|
||||
self.0 - other.0
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant(self.0 + *other)
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
Instant(self.0 - *other)
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,15 +47,11 @@ impl SystemTime {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime(self.0 + *other)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
self.0.checked_add(*other).map(|d| SystemTime(d))
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime(self.0 - *other)
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +42,6 @@ impl Timespec {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_duration(&self, other: &Duration) -> Timespec {
|
||||
self.checked_add_duration(other).expect("overflow when adding duration to time")
|
||||
}
|
||||
|
||||
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = other
|
||||
.as_secs()
|
||||
@ -68,27 +64,25 @@ impl Timespec {
|
||||
})
|
||||
}
|
||||
|
||||
fn sub_duration(&self, other: &Duration) -> Timespec {
|
||||
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = other
|
||||
.as_secs()
|
||||
.try_into() // <- target type would be `libc::time_t`
|
||||
.ok()
|
||||
.and_then(|secs| self.t.tv_sec.checked_sub(secs))
|
||||
.expect("overflow when subtracting duration from time");
|
||||
.and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
|
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
|
||||
if nsec < 0 {
|
||||
nsec += NSEC_PER_SEC as i32;
|
||||
secs = secs.checked_sub(1).expect("overflow when subtracting \
|
||||
duration from time");
|
||||
secs = secs.checked_sub(1)?;
|
||||
}
|
||||
Timespec {
|
||||
Some(Timespec {
|
||||
t: libc::timespec {
|
||||
tv_sec: secs,
|
||||
tv_nsec: nsec as _,
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,18 +159,16 @@ mod inner {
|
||||
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant {
|
||||
t: self.t.checked_add(dur2intervals(other))
|
||||
.expect("overflow when adding duration to instant"),
|
||||
}
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant {
|
||||
t: self.t.checked_add(checked_dur2intervals(other)?)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
Instant {
|
||||
t: self.t.checked_sub(dur2intervals(other))
|
||||
.expect("overflow when subtracting duration from instant"),
|
||||
}
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant {
|
||||
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,16 +191,12 @@ mod inner {
|
||||
self.t.sub_timespec(&other.t)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime { t: self.t.add_duration(other) }
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
self.t.checked_add_duration(other).map(|t| SystemTime { t })
|
||||
Some(SystemTime { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime { t: self.t.sub_duration(other) }
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,12 +224,12 @@ mod inner {
|
||||
}
|
||||
}
|
||||
|
||||
fn dur2intervals(dur: &Duration) -> u64 {
|
||||
fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
|
||||
let nanos = dur.as_secs()
|
||||
.checked_mul(NSEC_PER_SEC)?
|
||||
.checked_add(dur.subsec_nanos() as u64)?;
|
||||
let info = info();
|
||||
let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
|
||||
nanos.checked_add(dur.subsec_nanos() as u64)
|
||||
}).expect("overflow converting duration to nanoseconds");
|
||||
mul_div_u64(nanos, info.denom as u64, info.numer as u64)
|
||||
Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
|
||||
}
|
||||
|
||||
fn info() -> &'static libc::mach_timebase_info {
|
||||
@ -299,12 +287,12 @@ mod inner {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant { t: self.t.add_duration(other) }
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
Instant { t: self.t.sub_duration(other) }
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,16 +315,12 @@ mod inner {
|
||||
self.t.sub_timespec(&other.t)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime { t: self.t.add_duration(other) }
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
self.t.checked_add_duration(other).map(|t| SystemTime { t })
|
||||
Some(SystemTime { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime { t: self.t.sub_duration(other) }
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,12 +28,12 @@ impl Instant {
|
||||
self.0 - other.0
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
Instant(self.0 + *other)
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
Instant(self.0 - *other)
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,15 +47,11 @@ impl SystemTime {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime(self.0 + *other)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
self.0.checked_add(*other).map(|d| SystemTime(d))
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
SystemTime(self.0 - *other)
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
@ -68,30 +68,27 @@ impl Instant {
|
||||
Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> Instant {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
let freq = frequency() as u64;
|
||||
let t = other.as_secs().checked_mul(freq).and_then(|i| {
|
||||
(self.t as u64).checked_add(i)
|
||||
}).and_then(|i| {
|
||||
i.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq,
|
||||
NANOS_PER_SEC))
|
||||
}).expect("overflow when adding duration to time");
|
||||
Instant {
|
||||
let t = other.as_secs()
|
||||
.checked_mul(freq)?
|
||||
.checked_add(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))?
|
||||
.checked_add(self.t as u64)?;
|
||||
Some(Instant {
|
||||
t: t as c::LARGE_INTEGER,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> Instant {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
let freq = frequency() as u64;
|
||||
let t = other.as_secs().checked_mul(freq).and_then(|i| {
|
||||
(self.t as u64).checked_sub(i)
|
||||
}).and_then(|i| {
|
||||
i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq,
|
||||
NANOS_PER_SEC))
|
||||
}).expect("overflow when subtracting duration from time");
|
||||
Instant {
|
||||
i.checked_sub(mul_div_u64(other.subsec_nanos() as u64, freq, NANOS_PER_SEC))
|
||||
})?;
|
||||
Some(Instant {
|
||||
t: t as c::LARGE_INTEGER,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,20 +124,14 @@ impl SystemTime {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_duration(&self, other: &Duration) -> SystemTime {
|
||||
self.checked_add_duration(other).expect("overflow when adding duration to time")
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
checked_dur2intervals(other)
|
||||
.and_then(|d| self.intervals().checked_add(d))
|
||||
.map(|i| SystemTime::from_intervals(i))
|
||||
let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?;
|
||||
Some(SystemTime::from_intervals(intervals))
|
||||
}
|
||||
|
||||
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
|
||||
let intervals = self.intervals().checked_sub(dur2intervals(other))
|
||||
.expect("overflow when subtracting from time");
|
||||
SystemTime::from_intervals(intervals)
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?;
|
||||
Some(SystemTime::from_intervals(intervals))
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,16 +175,12 @@ impl Hash for SystemTime {
|
||||
}
|
||||
}
|
||||
|
||||
fn checked_dur2intervals(d: &Duration) -> Option<i64> {
|
||||
d.as_secs()
|
||||
.checked_mul(INTERVALS_PER_SEC)
|
||||
.and_then(|i| i.checked_add(d.subsec_nanos() as u64 / 100))
|
||||
.and_then(|i| i.try_into().ok())
|
||||
}
|
||||
|
||||
fn dur2intervals(d: &Duration) -> i64 {
|
||||
checked_dur2intervals(d)
|
||||
.expect("overflow when converting duration to intervals")
|
||||
fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
|
||||
dur.as_secs()
|
||||
.checked_mul(INTERVALS_PER_SEC)?
|
||||
.checked_add(dur.subsec_nanos() as u64 / 100)?
|
||||
.try_into()
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn intervals2dur(intervals: u64) -> Duration {
|
||||
|
@ -208,6 +208,22 @@ impl Instant {
|
||||
pub fn elapsed(&self) -> Duration {
|
||||
Instant::now() - *self
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
|
||||
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[unstable(feature = "time_checked_add", issue = "55940")]
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
|
||||
self.0.checked_add_duration(&duration).map(|t| Instant(t))
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[unstable(feature = "time_checked_add", issue = "55940")]
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
|
||||
self.0.checked_sub_duration(&duration).map(|t| Instant(t))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
@ -215,7 +231,8 @@ impl Add<Duration> for Instant {
|
||||
type Output = Instant;
|
||||
|
||||
fn add(self, other: Duration) -> Instant {
|
||||
Instant(self.0.add_duration(&other))
|
||||
self.checked_add(other)
|
||||
.expect("overflow when adding duration to instant")
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,7 +248,8 @@ impl Sub<Duration> for Instant {
|
||||
type Output = Instant;
|
||||
|
||||
fn sub(self, other: Duration) -> Instant {
|
||||
Instant(self.0.sub_duration(&other))
|
||||
self.checked_sub(other)
|
||||
.expect("overflow when subtracting duration from instant")
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,6 +383,14 @@ impl SystemTime {
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_add_duration(&duration).map(|t| SystemTime(t))
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[unstable(feature = "time_checked_add", issue = "55940")]
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_sub_duration(&duration).map(|t| SystemTime(t))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
@ -372,7 +398,8 @@ impl Add<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
fn add(self, dur: Duration) -> SystemTime {
|
||||
SystemTime(self.0.add_duration(&dur))
|
||||
self.checked_add(dur)
|
||||
.expect("overflow when adding duration to instant")
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,7 +415,8 @@ impl Sub<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
fn sub(self, dur: Duration) -> SystemTime {
|
||||
SystemTime(self.0.sub_duration(&dur))
|
||||
self.checked_sub(dur)
|
||||
.expect("overflow when subtracting duration from instant")
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,6 +549,20 @@ mod tests {
|
||||
|
||||
let second = Duration::new(1, 0);
|
||||
assert_almost_eq!(a - second + second, a);
|
||||
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
|
||||
|
||||
// checked_add_duration will not panic on overflow
|
||||
let mut maybe_t = Some(Instant::now());
|
||||
let max_duration = Duration::from_secs(u64::max_value());
|
||||
// in case `Instant` can store `>= now + max_duration`.
|
||||
for _ in 0..2 {
|
||||
maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
|
||||
}
|
||||
assert_eq!(maybe_t, None);
|
||||
|
||||
// checked_add_duration calculates the right time and will work for another year
|
||||
let year = Duration::from_secs(60 * 60 * 24 * 365);
|
||||
assert_eq!(a + year, a.checked_add(year).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -557,6 +599,7 @@ mod tests {
|
||||
.duration(), second);
|
||||
|
||||
assert_almost_eq!(a - second + second, a);
|
||||
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
|
||||
|
||||
// A difference of 80 and 800 years cannot fit inside a 32-bit time_t
|
||||
if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user