Add checked_sub for Instant and SystemTime
diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs
index fdd172a..6f02323 100644
--- a/src/libstd/sys/cloudabi/time.rs
+++ b/src/libstd/sys/cloudabi/time.rs
@@ -25,11 +25,6 @@
.checked_add(dur.subsec_nanos() as abi::timestamp)
}
-pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
- checked_dur2intervals(dur)
- .expect("overflow converting duration to nanoseconds")
-}
-
impl Instant {
pub fn now() -> Instant {
unsafe {
@@ -48,17 +43,15 @@
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
- checked_dur2intervals(other)?
- .checked_add(self.t)
- .map(|t| Instant {t})
+ 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)?)?,
+ })
}
}
@@ -94,17 +87,15 @@
}
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)?)?,
+ })
}
}
diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs
index 5ba8b78..cb2eab5 100644
--- a/src/libstd/sys/redox/time.rs
+++ b/src/libstd/sys/redox/time.rs
@@ -63,27 +63,25 @@
})
}
- 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,
},
- }
+ })
}
}
@@ -147,11 +145,11 @@
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
- self.t.checked_add_duration(other).map(|t| Instant { t })
+ 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)? })
}
}
@@ -175,11 +173,11 @@
}
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)? })
}
}
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
index 81ef0f4..8f8aaa8 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -64,27 +64,25 @@
})
}
- 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 _,
},
- }
+ })
}
}
@@ -162,14 +160,15 @@
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
- checked_dur2intervals(other)?.checked_add(self.t).map(|t| Instant {t})
+ 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)?)?,
+ })
}
}
@@ -193,11 +192,11 @@
}
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)? })
}
}
@@ -225,11 +224,6 @@
}
}
- fn dur2intervals(dur: &Duration) -> u64 {
- checked_dur2intervals(dur)
- .expect("overflow converting duration to nanoseconds")
- }
-
fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
let nanos = dur.as_secs()
.checked_mul(NSEC_PER_SEC)?
@@ -294,11 +288,11 @@
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
- self.t.checked_add_duration(other).map(|t| Instant { t })
+ 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)? })
}
}
@@ -322,11 +316,11 @@
}
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)? })
}
}
diff --git a/src/libstd/sys/wasm/time.rs b/src/libstd/sys/wasm/time.rs
index 20cd870..cc56773 100644
--- a/src/libstd/sys/wasm/time.rs
+++ b/src/libstd/sys/wasm/time.rs
@@ -29,11 +29,11 @@
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
- self.0.checked_add(*other).map(|d| Instant(d))
+ 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)?))
}
}
@@ -48,10 +48,10 @@
}
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)?))
}
}
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index cad3662..bb2c97e 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -79,16 +79,16 @@
})
}
- 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 {
+ })?;
+ Some(Instant {
t: t as c::LARGE_INTEGER,
- }
+ })
}
}
@@ -125,15 +125,13 @@
}
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))
}
}
@@ -185,11 +183,6 @@
.ok()
}
-fn dur2intervals(d: &Duration) -> i64 {
- checked_dur2intervals(d)
- .expect("overflow when converting duration to intervals")
-}
-
fn intervals2dur(intervals: u64) -> Duration {
Duration::new(intervals / INTERVALS_PER_SEC,
((intervals % INTERVALS_PER_SEC) * 100) as u32)
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index a0703fd..63cede7 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -216,6 +216,14 @@
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")]
@@ -240,7 +248,8 @@
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")
}
}
@@ -374,6 +383,14 @@
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")]
@@ -398,7 +415,8 @@
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")
}
}
@@ -531,6 +549,7 @@
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());
@@ -580,6 +599,7 @@
.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) {