Skip to content

Commit d4b35f7

Browse files
committed
Add saturating methods for Duration
1 parent 56ed7bb commit d4b35f7

File tree

4 files changed

+130
-0
lines changed

4 files changed

+130
-0
lines changed

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#![feature(doc_cfg)]
101101
#![feature(doc_spotlight)]
102102
#![feature(duration_consts_2)]
103+
#![feature(duration_saturating_ops)]
103104
#![feature(extern_types)]
104105
#![feature(fundamental)]
105106
#![feature(intrinsics)]

core/src/time.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,34 @@ impl Duration {
108108
#[unstable(feature = "duration_constants", issue = "57391")]
109109
pub const NANOSECOND: Duration = Duration::from_nanos(1);
110110

111+
/// The minimum duration.
112+
///
113+
/// # Examples
114+
///
115+
/// ```
116+
/// #![feature(duration_constants)]
117+
/// use std::time::Duration;
118+
///
119+
/// assert_eq!(Duration::MIN, Duration::new(0, 0));
120+
/// ```
121+
#[unstable(feature = "duration_constants", issue = "57391")]
122+
pub const MIN: Duration = Duration::from_nanos(0);
123+
124+
/// The maximum duration.
125+
///
126+
/// It is roughly equal to a duration of 584,942,417,355 years.
127+
///
128+
/// # Examples
129+
///
130+
/// ```
131+
/// #![feature(duration_constants)]
132+
/// use std::time::Duration;
133+
///
134+
/// assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1));
135+
/// ```
136+
#[unstable(feature = "duration_constants", issue = "57391")]
137+
pub const MAX: Duration = Duration::new(u64::MAX, NANOS_PER_SEC - 1);
138+
111139
/// Creates a new `Duration` from the specified number of whole seconds and
112140
/// additional nanoseconds.
113141
///
@@ -450,6 +478,29 @@ impl Duration {
450478
}
451479
}
452480

481+
/// Saturating `Duration` addition. Computes `self + other`, returning [`Duration::MAX`]
482+
/// if overflow occurred.
483+
///
484+
/// # Examples
485+
///
486+
/// ```
487+
/// #![feature(duration_saturating_ops)]
488+
/// #![feature(duration_constants)]
489+
/// use std::time::Duration;
490+
///
491+
/// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
492+
/// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX);
493+
/// ```
494+
#[unstable(feature = "duration_saturating_ops", issue = "76416")]
495+
#[inline]
496+
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
497+
pub const fn saturating_add(self, rhs: Duration) -> Duration {
498+
match self.checked_add(rhs) {
499+
Some(res) => res,
500+
None => Duration::MAX,
501+
}
502+
}
503+
453504
/// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
454505
/// if the result would be negative or if overflow occurred.
455506
///
@@ -485,6 +536,29 @@ impl Duration {
485536
}
486537
}
487538

539+
/// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::MIN`]
540+
/// if the result would be negative or if overflow occurred.
541+
///
542+
/// # Examples
543+
///
544+
/// ```
545+
/// #![feature(duration_saturating_ops)]
546+
/// #![feature(duration_constants)]
547+
/// use std::time::Duration;
548+
///
549+
/// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
550+
/// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::MIN);
551+
/// ```
552+
#[unstable(feature = "duration_saturating_ops", issue = "76416")]
553+
#[inline]
554+
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
555+
pub const fn saturating_sub(self, rhs: Duration) -> Duration {
556+
match self.checked_sub(rhs) {
557+
Some(res) => res,
558+
None => Duration::MIN,
559+
}
560+
}
561+
488562
/// Checked `Duration` multiplication. Computes `self * other`, returning
489563
/// [`None`] if overflow occurred.
490564
///
@@ -515,6 +589,29 @@ impl Duration {
515589
None
516590
}
517591

592+
/// Saturating `Duration` multiplication. Computes `self * other`, returning
593+
/// [`Duration::MAX`] if overflow occurred.
594+
///
595+
/// # Examples
596+
///
597+
/// ```
598+
/// #![feature(duration_saturating_ops)]
599+
/// #![feature(duration_constants)]
600+
/// use std::time::Duration;
601+
///
602+
/// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2));
603+
/// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX);
604+
/// ```
605+
#[unstable(feature = "duration_saturating_ops", issue = "76416")]
606+
#[inline]
607+
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
608+
pub const fn saturating_mul(self, rhs: u32) -> Duration {
609+
match self.checked_mul(rhs) {
610+
Some(res) => res,
611+
None => Duration::MAX,
612+
}
613+
}
614+
518615
/// Checked `Duration` division. Computes `self / other`, returning [`None`]
519616
/// if `other == 0`.
520617
///

core/tests/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#![feature(core_private_diy_float)]
1111
#![feature(debug_non_exhaustive)]
1212
#![feature(dec2flt)]
13+
#![feature(duration_constants)]
14+
#![feature(duration_saturating_ops)]
1315
#![feature(exact_size_is_empty)]
1416
#![feature(fixed_size_array)]
1517
#![feature(flt2dec)]

core/tests/time.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ fn checked_add() {
8989
assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
9090
}
9191

92+
#[test]
93+
fn saturating_add() {
94+
assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
95+
assert_eq!(
96+
Duration::new(0, 500_000_000).saturating_add(Duration::new(0, 500_000_001)),
97+
Duration::new(1, 1)
98+
);
99+
assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX);
100+
}
101+
92102
#[test]
93103
fn sub() {
94104
assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), Duration::new(0, 1));
@@ -107,6 +117,17 @@ fn checked_sub() {
107117
assert_eq!(zero.checked_sub(one_sec), None);
108118
}
109119

120+
#[test]
121+
fn saturating_sub() {
122+
let zero = Duration::new(0, 0);
123+
let one_nano = Duration::new(0, 1);
124+
let one_sec = Duration::new(1, 0);
125+
assert_eq!(one_nano.saturating_sub(zero), Duration::new(0, 1));
126+
assert_eq!(one_sec.saturating_sub(one_nano), Duration::new(0, 999_999_999));
127+
assert_eq!(zero.saturating_sub(one_nano), Duration::MIN);
128+
assert_eq!(zero.saturating_sub(one_sec), Duration::MIN);
129+
}
130+
110131
#[test]
111132
#[should_panic]
112133
fn sub_bad1() {
@@ -136,6 +157,15 @@ fn checked_mul() {
136157
assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None);
137158
}
138159

160+
#[test]
161+
fn saturating_mul() {
162+
assert_eq!(Duration::new(0, 1).saturating_mul(2), Duration::new(0, 2));
163+
assert_eq!(Duration::new(1, 1).saturating_mul(3), Duration::new(3, 3));
164+
assert_eq!(Duration::new(0, 500_000_001).saturating_mul(4), Duration::new(2, 4));
165+
assert_eq!(Duration::new(0, 500_000_001).saturating_mul(4000), Duration::new(2000, 4000));
166+
assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX);
167+
}
168+
139169
#[test]
140170
fn div() {
141171
assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));

0 commit comments

Comments
 (0)