use core::time::Duration;
#[inline]
#[must_use]
pub(crate) fn saturating_mul_f64(base: Duration, factor: f64) -> Duration {
if factor.is_nan() || factor <= 0.0 || base.is_zero() {
return Duration::ZERO;
}
if factor.is_infinite() {
return Duration::MAX;
}
let secs = base.as_secs_f64() * factor;
if secs <= 0.0 {
return Duration::ZERO;
}
if !secs.is_finite() {
return Duration::MAX;
}
match Duration::try_from_secs_f64(secs) {
Ok(d) => d,
Err(_) => Duration::MAX,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn handles_pathological_factors() {
let base = Duration::from_secs(1);
assert_eq!(saturating_mul_f64(base, f64::NAN), Duration::ZERO);
assert_eq!(saturating_mul_f64(base, f64::INFINITY), Duration::MAX);
assert_eq!(saturating_mul_f64(base, -1.0), Duration::ZERO);
assert_eq!(saturating_mul_f64(base, 0.0), Duration::ZERO);
assert_eq!(saturating_mul_f64(Duration::ZERO, 10.0), Duration::ZERO);
}
#[test]
fn saturates_at_max_instead_of_panicking() {
let grown = saturating_mul_f64(Duration::MAX, 2.0);
assert_eq!(grown, Duration::MAX);
}
#[test]
fn ordinary_multiplication_is_exact_enough() {
let d = saturating_mul_f64(Duration::from_millis(100), 1.5);
assert_eq!(d, Duration::from_millis(150));
}
}