about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorLinus Färnstrand <faern@faern.net>2018-12-10 23:55:53 +0100
committerLinus Färnstrand <faern@faern.net>2018-12-13 15:25:14 +0100
commitf5a99c321b14e69e9d9a6ffaac3a5b7b8906c1f2 (patch)
tree609e631c35b2ba6db599e74111d9adc02eb57e7d /src/libstd
parent13f0463a195832f10f0f22105ad14e6d6b2eff59 (diff)
downloadrust-f5a99c321b14e69e9d9a6ffaac3a5b7b8906c1f2.tar.gz
rust-f5a99c321b14e69e9d9a6ffaac3a5b7b8906c1f2.zip
Add checked_sub for Instant and SystemTime
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/sys/cloudabi/time.rs37
-rw-r--r--src/libstd/sys/redox/time.rs24
-rw-r--r--src/libstd/sys/unix/time.rs48
-rw-r--r--src/libstd/sys/wasm/time.rs12
-rw-r--r--src/libstd/sys/windows/time.rs25
-rw-r--r--src/libstd/time.rs24
6 files changed, 83 insertions, 87 deletions
diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs
index fdd172a896c..6f023230a27 100644
--- a/src/libstd/sys/cloudabi/time.rs
+++ b/src/libstd/sys/cloudabi/time.rs
@@ -25,11 +25,6 @@ fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
         .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 @@ impl Instant {
     }
 
     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 @@ impl SystemTime {
     }
 
     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 5ba8b780727..cb2eab52211 100644
--- a/src/libstd/sys/redox/time.rs
+++ b/src/libstd/sys/redox/time.rs
@@ -63,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,
             },
-        }
+        })
     }
 }
 
@@ -147,11 +145,11 @@ impl Instant {
     }
 
     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 @@ impl SystemTime {
     }
 
     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 81ef0f48833..8f8aaa88b22 100644
--- a/src/libstd/sys/unix/time.rs
+++ b/src/libstd/sys/unix/time.rs
@@ -64,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 _,
             },
-        }
+        })
     }
 }
 
@@ -162,14 +160,15 @@ mod inner {
         }
 
         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 @@ mod inner {
         }
 
         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 @@ mod inner {
         }
     }
 
-    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 @@ mod inner {
         }
 
         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 @@ mod inner {
         }
 
         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 20cd870919c..cc56773e0ea 100644
--- a/src/libstd/sys/wasm/time.rs
+++ b/src/libstd/sys/wasm/time.rs
@@ -29,11 +29,11 @@ impl Instant {
     }
 
     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 @@ impl SystemTime {
     }
 
     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 cad36627bf3..bb2c97ea149 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -79,16 +79,16 @@ impl Instant {
         })
     }
 
-    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 @@ impl SystemTime {
     }
 
     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 @@ fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
         .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 a0703fd50d5..63cede79e48 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -216,6 +216,14 @@ impl Instant {
     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 @@ 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")
     }
 }
 
@@ -374,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")]
@@ -398,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")
     }
 }
 
@@ -531,6 +549,7 @@ 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());
@@ -580,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) {