use crate::abi;
use core::{convert::TryFrom, time::Duration as StdDuration};
use super::Duration;
#[cfg_attr(
feature = "nightly",
doc = "[`timeout!`] can be used to construct a `Timeout` in a concise syntax."
)]
#[cfg_attr(
not(feature = "nightly"),
doc = "If `nightly` feature is enabled, \
`timeout!` can be used to construct a `Timeout` in a concise syntax."
)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct Timeout {
value: abi::TMO,
}
impl Timeout {
pub const ZERO: Self = unsafe { Self::from_raw(abi::TMO_POL) };
pub const FOREVER: Self = unsafe { Self::from_raw(abi::TMO_FEVR) };
#[inline]
pub const unsafe fn from_raw(value: abi::TMO) -> Self {
Self { value }
}
#[inline]
pub const fn as_raw(self) -> abi::TMO {
self.value
}
#[inline]
pub const fn is_finite(self) -> bool {
self.value != Self::FOREVER.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)
}
}
pub struct TryFromDurationError(pub(super) ());
impl TryFrom<StdDuration> for Timeout {
type Error = TryFromDurationError;
#[inline]
fn try_from(d: StdDuration) -> Result<Self, Self::Error> {
Self::from_nanos(d.as_nanos()).ok_or(TryFromDurationError(()))
}
}
impl TryFrom<Duration> for Timeout {
type Error = TryFromDurationError;
#[inline]
fn try_from(d: Duration) -> Result<Self, Self::Error> {
match () {
() => {
Ok(unsafe { Self::from_raw(d.as_raw()) })
}
}
}
}
#[cfg(feature = "nightly")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "nightly")))]
pub macro timeout {
($kind:tt: $value:literal) => {{
const VALUE: $crate::time::Timeout = $crate::time::timeout!($kind: ($value));
VALUE
}},
(s: $value:expr) => {
$crate::time::expect_valid_timeout($crate::time::Timeout::from_secs($value))
},
(ms: $value:expr) => {
$crate::time::expect_valid_timeout($crate::time::Timeout::from_millis($value))
},
(us: $value:expr) => {
$crate::time::expect_valid_timeout($crate::time::Timeout::from_micros($value))
},
(μs: $value:expr) => {
$crate::time::expect_valid_timeout($crate::time::Timeout::from_micros($value))
},
(ns: $value:expr) => {
$crate::time::expect_valid_timeout($crate::time::Timeout::from_nanos($value))
},
(infinity) => { $crate::time::Timeout::FOREVER },
(0) => { $crate::time::Timeout::ZERO },
}
#[cfg(feature = "nightly")]
#[doc(hidden)]
#[track_caller]
#[inline]
pub const fn expect_valid_timeout(x: Option<Timeout>) -> Timeout {
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 {}
}
}