pipecircuit 0.0.16

Correct. Robust. Fast. Portable.
Documentation
use core::num::NonZeroU64;

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum WakePrecision {
    Nanosecond,
    Microsecond,
    Millisecond,
    Second,
}

impl WakePrecision {
    pub const fn nanoseconds_per_tick(self) -> NonZeroU64 {
        match self {
            Self::Nanosecond => NonZeroU64::MIN,
            Self::Microsecond => nonzero(1_000),
            Self::Millisecond => nonzero(1_000_000),
            Self::Second => nonzero(1_000_000_000),
        }
    }
}

#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct WakeAfter {
    ticks: NonZeroU64,
    precision: WakePrecision,
}

impl WakeAfter {
    pub const fn nanoseconds(ticks: NonZeroU64) -> Self {
        Self::new(ticks, WakePrecision::Nanosecond)
    }

    pub const fn microseconds(ticks: NonZeroU64) -> Self {
        Self::new(ticks, WakePrecision::Microsecond)
    }

    pub const fn milliseconds(ticks: NonZeroU64) -> Self {
        Self::new(ticks, WakePrecision::Millisecond)
    }

    pub const fn seconds(ticks: NonZeroU64) -> Self {
        Self::new(ticks, WakePrecision::Second)
    }

    pub const fn new(ticks: NonZeroU64, precision: WakePrecision) -> Self {
        Self { ticks, precision }
    }

    pub const fn ticks(self) -> NonZeroU64 {
        self.ticks
    }

    pub const fn precision(self) -> WakePrecision {
        self.precision
    }

    pub const fn checked_nanoseconds(self) -> Option<NonZeroU64> {
        let nanoseconds = self
            .ticks
            .get()
            .checked_mul(self.precision.nanoseconds_per_tick().get());
        match nanoseconds {
            Some(nanoseconds) => NonZeroU64::new(nanoseconds),
            None => None,
        }
    }
}

const fn nonzero(value: u64) -> NonZeroU64 {
    match NonZeroU64::new(value) {
        Some(value) => value,
        None => NonZeroU64::MIN,
    }
}