#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]
use std::time::{Duration, Instant, SystemTime};
mod internal;
pub trait SaturatingTime: internal::SaturatingTime {
fn max_value() -> Self {
internal::SaturatingTime::max_value()
}
fn min_value() -> Self {
internal::SaturatingTime::min_value()
}
fn saturating_add(self, duration: Duration) -> Self {
self.checked_add(duration)
.unwrap_or(SaturatingTime::max_value())
}
fn saturating_sub(self, duration: Duration) -> Self {
self.checked_sub(duration)
.unwrap_or(SaturatingTime::min_value())
}
}
impl SaturatingTime for SystemTime {}
impl SaturatingTime for Instant {}
#[cfg(test)]
mod tests {
use super::*;
use crate::internal;
use std::{
fmt::Debug,
ops::{Add, Sub},
time::{Instant, SystemTime},
};
fn min_max<T: SaturatingTime + PartialEq + Debug>() {
assert_eq!(
<T as SaturatingTime>::max_value(),
<T as internal::SaturatingTime>::max_value()
);
assert_eq!(
<T as SaturatingTime>::min_value(),
<T as internal::SaturatingTime>::min_value()
);
}
fn saturating<
T: SaturatingTime + PartialEq + Debug + Add<Duration, Output = T> + Sub<Duration, Output = T>,
>() {
let max = <T as SaturatingTime>::max_value();
assert_eq!(max.saturating_add(Duration::ZERO), max);
assert_eq!(max.saturating_add(Duration::new(0, 1)), max);
assert_eq!(max.saturating_sub(Duration::ZERO), max);
assert_eq!(
max.saturating_sub(Duration::new(0, 1)),
max - Duration::new(0, 1)
);
let min = <T as SaturatingTime>::min_value();
assert_eq!(min.saturating_sub(Duration::ZERO), min);
assert_eq!(min.saturating_sub(Duration::new(0, 1)), min);
assert_eq!(min.saturating_add(Duration::ZERO), min);
assert_eq!(
min.saturating_add(Duration::new(0, 1)),
min + Duration::new(0, 1)
);
}
#[test]
fn system_time_min_max() {
min_max::<SystemTime>();
}
#[test]
fn instant_min_max() {
min_max::<Instant>();
}
#[test]
fn system_time_saturating() {
saturating::<SystemTime>();
}
#[test]
fn instant_saturating() {
saturating::<Instant>();
}
}