use crate::abi;
use core::{convert::TryFrom, time::Duration as StdDuration};
use super::Timeout;
#[cfg_attr(
feature = "nightly",
doc = "[`duration!`] can be used to construct a `Duration` in a concise syntax."
)]
#[cfg_attr(
not(feature = "nightly"),
doc = "If `nightly` feature is enabled, \
`duration!` can be used to construct a `Duration` in a concise syntax."
)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Duration {
value: abi::RELTIM,
}
impl Duration {
pub const ZERO: Self = unsafe { Self::from_raw(0) };
#[inline]
pub const unsafe fn from_raw(value: abi::RELTIM) -> Self {
Self { value }
}
#[inline]
pub const fn as_raw(self) -> abi::RELTIM {
self.value
}
#[inline]
pub const fn from_secs(secs: u64) -> Option<Self> {
if secs > u64::MAX / 1_000_000 {
None
} else {
Self::from_micros(secs * 1_000_000)
}
}
#[inline]
pub const fn from_millis(millis: u64) -> Option<Self> {
if millis > u64::MAX / 1_000 {
None
} else {
Self::from_micros(millis * 1_000)
}
}
#[inline]
pub const fn from_micros(micros: u64) -> Option<Self> {
match () {
() => {
if micros > abi::TMAX_RELTIM as u64 {
None
} else {
Some(unsafe { Self::from_raw(micros as u32) })
}
}
}
}
#[inline]
pub fn from_nanos(nanos: u128) -> Option<Self> {
u64::try_from(nanos / 1_000)
.ok()
.and_then(Self::from_micros)
}
}
impl TryFrom<StdDuration> for Duration {
type Error = super::TryFromDurationError;
#[inline]
fn try_from(d: StdDuration) -> Result<Self, Self::Error> {
Self::from_nanos(d.as_nanos()).ok_or(super::TryFromDurationError(()))
}
}
impl TryFrom<Timeout> for Duration {
type Error = super::TryFromDurationError;
#[inline]
fn try_from(d: Timeout) -> Result<Self, Self::Error> {
match () {
() => {
if d.is_finite() {
Ok(unsafe { Self::from_raw(d.as_raw()) })
} else {
Err(super::TryFromDurationError(()))
}
}
}
}
}
#[cfg(feature = "nightly")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "nightly")))]
pub macro duration {
($kind:tt: $value:literal) => {{
const VALUE: $crate::time::Duration = $crate::time::duration!($kind: ($value));
VALUE
}},
(s: $value:expr) => {
$crate::time::expect_valid_duration($crate::time::Duration::from_secs($value))
},
(ms: $value:expr) => {
$crate::time::expect_valid_duration($crate::time::Duration::from_millis($value))
},
(us: $value:expr) => {
$crate::time::expect_valid_duration($crate::time::Duration::from_micros($value))
},
(μs: $value:expr) => {
$crate::time::expect_valid_duration($crate::time::Duration::from_micros($value))
},
(ns: $value:expr) => {
$crate::time::expect_valid_duration($crate::time::Duration::from_nanos($value))
},
(0) => { $crate::time::Duration::ZERO },
}
#[cfg(feature = "nightly")]
#[doc(hidden)]
#[track_caller]
#[inline]
pub const fn expect_valid_duration(x: Option<Duration>) -> Duration {
if let Some(x) = x {
x
} else {
let zero = 0u32;
#[allow(unconditional_panic)]
let __the_specified_timeout_is_invalid_or_not_representable__ = 1 / zero;
#[allow(clippy::empty_loop)]
loop {}
}
}