use core::fmt;
use crate::divide::div_rem;
use crate::{Duration, NANOS_PER_SEC};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DurationTooLong(());
impl fmt::Display for DurationTooLong {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("duration longer than u64::MAX nanoseconds (about 584 years)")
}
}
impl core::error::Error for DurationTooLong {}
impl Duration {
const fn checked_from_core(duration: core::time::Duration) -> Option<Self> {
match duration.as_secs().checked_mul(NANOS_PER_SEC) {
Some(whole) => match whole.checked_add(duration.subsec_nanos() as u64) {
Some(nanos) => Some(Self::from_nanos(nanos)),
None => None,
},
None => None,
}
}
#[must_use]
pub const fn saturating_from_core(duration: core::time::Duration) -> Self {
match Self::checked_from_core(duration) {
Some(duration) => duration,
None => Self::MAX,
}
}
}
impl TryFrom<core::time::Duration> for Duration {
type Error = DurationTooLong;
fn try_from(duration: core::time::Duration) -> Result<Self, DurationTooLong> {
Self::checked_from_core(duration).ok_or(DurationTooLong(()))
}
}
impl From<Duration> for core::time::Duration {
fn from(duration: Duration) -> Self {
let (secs, nanos) = div_rem(duration.as_nanos(), NANOS_PER_SEC);
Self::new(secs, nanos as u32)
}
}