use core::time::Duration as UnsignedDuration;
use crate::{
error::{duration::Error as E, ErrorContext},
Error, SignedDuration, Span,
};
#[derive(Clone, Copy, Debug)]
pub(crate) enum Duration {
Span(Span),
Signed(SignedDuration),
Unsigned(UnsignedDuration),
}
impl Duration {
#[cfg_attr(feature = "perf-inline", inline(always))]
pub(crate) fn to_signed(&self) -> Result<SDuration<'_>, Error> {
match *self {
Duration::Span(ref span) => Ok(SDuration::Span(span)),
Duration::Signed(sdur) => Ok(SDuration::Absolute(sdur)),
Duration::Unsigned(udur) => {
let sdur = SignedDuration::try_from(udur)
.context(E::RangeUnsignedDuration)?;
Ok(SDuration::Absolute(sdur))
}
}
}
#[cfg_attr(feature = "perf-inline", inline(always))]
pub(crate) fn checked_neg(self) -> Result<Duration, Error> {
match self {
Duration::Span(span) => Ok(Duration::Span(span.negate())),
Duration::Signed(sdur) => {
if let Some(sdur) = sdur.checked_neg() {
Ok(Duration::Signed(sdur))
} else {
let udur = UnsignedDuration::new(
i64::MIN.unsigned_abs(),
sdur.subsec_nanos().unsigned_abs(),
);
Ok(Duration::Unsigned(udur))
}
}
Duration::Unsigned(udur) => {
let sdur = if udur.as_secs() == i64::MIN.unsigned_abs() {
SignedDuration::new_without_nano_overflow(
i64::MIN,
-i32::try_from(udur.subsec_nanos()).unwrap(),
)
} else {
-SignedDuration::try_from(udur)
.context(E::FailedNegateUnsignedDuration)?
};
Ok(Duration::Signed(sdur))
}
}
}
#[cfg_attr(feature = "perf-inline", inline(always))]
pub(crate) fn is_negative(&self) -> bool {
match *self {
Duration::Span(ref span) => span.is_negative(),
Duration::Signed(ref sdur) => sdur.is_negative(),
Duration::Unsigned(_) => false,
}
}
}
impl From<Span> for Duration {
#[inline]
fn from(span: Span) -> Duration {
Duration::Span(span)
}
}
impl From<SignedDuration> for Duration {
#[inline]
fn from(sdur: SignedDuration) -> Duration {
Duration::Signed(sdur)
}
}
impl From<UnsignedDuration> for Duration {
#[inline]
fn from(udur: UnsignedDuration) -> Duration {
Duration::Unsigned(udur)
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum SDuration<'a> {
Span(&'a Span),
Absolute(SignedDuration),
}