use core::{cmp::Ordering, convert, marker::PhantomData, ops};
use num_traits::PrimInt;
use typenum::{NonZero, Unsigned, U100, U36};
use crate::{helpers::Helpers, Rate};
mod period;
pub use period::Period;
#[macro_use]
mod macros;
#[derive(Clone, Copy, Debug)]
pub struct Duration<T, Numer, Denom>
where
T: PrimInt,
Denom: NonZero,
{
pub(crate) ticks: T,
pub(crate) _period: Period<Numer, Denom>,
}
impl_duration_for_integer!(u32);
impl_duration_for_integer!(u64);
impl<T, Numer, Denom> Duration<T, Numer, Denom>
where
T: PrimInt,
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
#[inline]
pub const fn from_ticks(ticks: T) -> Self {
Self {
ticks,
_period: Period {
_numer: PhantomData,
_denom: PhantomData,
},
}
}
#[inline]
pub const fn ticks(&self) -> T {
self.ticks
}
}
impl<ST, OT, Numer, Denom> ops::Sub<Duration<OT, Numer, Denom>> for Duration<ST, Numer, Denom>
where
ST: PrimInt + From<OT>,
OT: PrimInt,
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
type Output = Duration<ST, Numer, Denom>;
#[inline]
fn sub(self, other: Duration<OT, Numer, Denom>) -> Self::Output {
if let Some(v) = self.ticks.checked_sub(&other.ticks.into()) {
Self {
ticks: v,
_period: Period::default(),
}
} else {
panic!("Sub failed!");
}
}
}
impl<ST, OT, Numer, Denom> ops::SubAssign<Duration<OT, Numer, Denom>> for Duration<ST, Numer, Denom>
where
ST: PrimInt,
OT: PrimInt,
Self: ops::Sub<Duration<OT, Numer, Denom>, Output = Self>,
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
#[inline]
fn sub_assign(&mut self, other: Duration<OT, Numer, Denom>) {
*self = *self - other;
}
}
impl<Numer, Denom> From<Duration<u32, Numer, Denom>> for Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
#[inline]
fn from(val: Duration<u32, Numer, Denom>) -> Duration<u64, Numer, Denom> {
Duration::<u64, Numer, Denom>::from_ticks(val.ticks() as u64)
}
}
impl<Numer, Denom> convert::TryFrom<Duration<u64, Numer, Denom>> for Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
type Error = ();
#[inline]
fn try_from(val: Duration<u64, Numer, Denom>) -> Result<Duration<u32, Numer, Denom>, ()> {
Ok(Duration::<u32, Numer, Denom>::from_ticks(
val.ticks().try_into().map_err(|_| ())?,
))
}
}
impl<ST, OT, Numer, Denom> ops::Add<Duration<OT, Numer, Denom>> for Duration<ST, Numer, Denom>
where
ST: PrimInt + From<OT>,
OT: PrimInt,
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
type Output = Duration<ST, Numer, Denom>;
#[inline]
fn add(self, other: Duration<OT, Numer, Denom>) -> Self::Output {
if let Some(v) = self.ticks.checked_add(&other.ticks().into()) {
Self {
ticks: v,
_period: Period::default(),
}
} else {
panic!("Add failed!");
}
}
}
impl<ST, OT, Numer, Denom> ops::AddAssign<Duration<OT, Numer, Denom>> for Duration<ST, Numer, Denom>
where
ST: PrimInt + From<OT>,
OT: PrimInt,
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
#[inline]
fn add_assign(&mut self, other: Duration<OT, Numer, Denom>) {
*self = *self + other;
}
}
impl<LNumer, LDenom, RNumer, RDenom> PartialOrd<Duration<u32, RNumer, RDenom>>
for Duration<u64, LNumer, LDenom>
where
LNumer: Unsigned,
LDenom: Unsigned + NonZero,
RNumer: Unsigned,
RDenom: Unsigned + NonZero,
{
#[inline]
fn partial_cmp(&self, other: &Duration<u32, RNumer, RDenom>) -> Option<Ordering> {
self.partial_cmp(&Duration::<u64, RNumer, RDenom>::from_ticks(
other.ticks() as u64
))
}
}
impl<LNumer, LDenom, RNumer, RDenom> PartialEq<Duration<u32, RNumer, RDenom>>
for Duration<u64, LNumer, LDenom>
where
LNumer: Unsigned,
LDenom: Unsigned + NonZero,
RNumer: Unsigned,
RDenom: Unsigned + NonZero,
{
#[inline]
fn eq(&self, other: &Duration<u32, RNumer, RDenom>) -> bool {
self.eq(&Duration::<u64, RNumer, RDenom>::from_ticks(
other.ticks() as u64
))
}
}
impl<LNumer, LDenom, RNumer, RDenom> PartialOrd<Duration<u64, RNumer, RDenom>>
for Duration<u32, LNumer, LDenom>
where
LNumer: Unsigned,
LDenom: Unsigned + NonZero,
RNumer: Unsigned,
RDenom: Unsigned + NonZero,
{
#[inline]
fn partial_cmp(&self, other: &Duration<u64, RNumer, RDenom>) -> Option<Ordering> {
Duration::<u64, LNumer, LDenom>::from_ticks(self.ticks as u64).partial_cmp(other)
}
}
impl<LNumer, LDenom, RNumer, RDenom> PartialEq<Duration<u64, RNumer, RDenom>>
for Duration<u32, LNumer, LDenom>
where
LNumer: Unsigned,
LDenom: Unsigned + NonZero,
RNumer: Unsigned,
RDenom: Unsigned + NonZero,
{
#[inline]
fn eq(&self, other: &Duration<u64, RNumer, RDenom>) -> bool {
Duration::<u64, LNumer, LDenom>::from_ticks(self.ticks as u64).eq(other)
}
}
pub trait ExtU32 {
fn nanos<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn micros<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn millis<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn secs<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn minutes<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn hours<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
}
impl ExtU32 for u32 {
#[inline]
fn nanos<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::nanos(self)
}
#[inline]
fn micros<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::micros(self)
}
#[inline]
fn millis<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::millis(self)
}
#[inline]
fn secs<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::secs(self)
}
#[inline]
fn minutes<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::minutes(self)
}
#[inline]
fn hours<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::hours(self)
}
}
pub trait ExtU32Ceil {
fn nanos_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn micros_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn millis_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn secs_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn minutes_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn hours_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
}
impl ExtU32Ceil for u32 {
#[inline]
fn nanos_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::nanos_at_least(self)
}
#[inline]
fn micros_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::micros_at_least(self)
}
#[inline]
fn millis_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::millis_at_least(self)
}
#[inline]
fn secs_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::secs_at_least(self)
}
#[inline]
fn minutes_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::minutes_at_least(self)
}
#[inline]
fn hours_at_least<Numer, Denom>(self) -> Duration<u32, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u32, Numer, Denom>::hours_at_least(self)
}
}
pub trait ExtU64 {
fn nanos<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn micros<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn millis<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn secs<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn minutes<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn hours<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
}
impl ExtU64 for u64 {
#[inline]
fn nanos<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::nanos(self)
}
#[inline]
fn micros<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::micros(self)
}
#[inline]
fn millis<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::millis(self)
}
#[inline]
fn secs<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::secs(self)
}
#[inline]
fn minutes<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::minutes(self)
}
#[inline]
fn hours<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::hours(self)
}
}
pub trait ExtU64Ceil {
fn nanos_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn micros_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn millis_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn secs_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn minutes_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
fn hours_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero;
}
impl ExtU64Ceil for u64 {
#[inline]
fn nanos_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::nanos_at_least(self)
}
#[inline]
fn micros_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::micros_at_least(self)
}
#[inline]
fn millis_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::millis_at_least(self)
}
#[inline]
fn secs_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::secs_at_least(self)
}
#[inline]
fn minutes_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::minutes_at_least(self)
}
#[inline]
fn hours_at_least<Numer, Denom>(self) -> Duration<u64, Numer, Denom>
where
Numer: Unsigned,
Denom: Unsigned + NonZero,
{
Duration::<u64, Numer, Denom>::hours_at_least(self)
}
}