mod wake_after;
use core::{marker::PhantomData, num::NonZeroU64};
use crate::Pipe;
pub use wake_after::{WakeAfter, WakePrecision};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct TimerToken(NonZeroU64);
impl TimerToken {
pub const MIN: Self = Self(NonZeroU64::MIN);
pub const fn from_nonzero(value: NonZeroU64) -> Self {
Self(value)
}
pub const fn value(self) -> NonZeroU64 {
self.0
}
}
impl From<NonZeroU64> for TimerToken {
fn from(value: NonZeroU64) -> Self {
Self::from_nonzero(value)
}
}
impl From<TimerToken> for NonZeroU64 {
fn from(token: TimerToken) -> Self {
token.value()
}
}
#[cfg(feature = "storage")]
impl crate::storage::warp_table::IndexKey for TimerToken {
fn index_word(self) -> u64 {
crate::storage::warp_table::integer_index_word(self.value().get())
}
}
pub enum Timer<Token> {
_Token(PhantomData<fn() -> Token>),
}
impl<Token: 'static> Pipe for Timer<Token> {
type In<'message> = TimerIn<Token>;
type Out<'message> = TimerOut<'message, Token>;
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TimerIn<Token> {
Arm { token: Token, after: WakeAfter },
Cancel { token: Token },
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TimerArmRefusal {
AlreadyArmed,
AtCapacity { maximum_deadlines: u32 },
WakeTickOutsideRange,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TimerCancellationRefusal {
NotArmed,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EmptyElapsedTimerTokens;
#[derive(Debug, Eq, PartialEq)]
pub struct ElapsedTimerTokens<'tokens, Token> {
tokens: &'tokens [Token],
}
impl<'tokens, Token> ElapsedTimerTokens<'tokens, Token> {
pub const fn try_new(tokens: &'tokens [Token]) -> Result<Self, EmptyElapsedTimerTokens> {
if tokens.is_empty() {
return Err(EmptyElapsedTimerTokens);
}
Ok(Self { tokens })
}
pub const fn tokens(&self) -> &'tokens [Token] {
self.tokens
}
}
#[derive(Debug, Eq, PartialEq)]
#[must_use = "timer outcomes must be routed or settled"]
pub enum TimerOut<'message, Token> {
Armed {
token: Token,
},
Elapsed {
tokens: ElapsedTimerTokens<'message, Token>,
},
Cancelled {
token: Token,
},
ArmRefused {
token: Token,
after: WakeAfter,
reason: TimerArmRefusal,
},
CancellationRefused {
token: Token,
reason: TimerCancellationRefusal,
},
}
pub struct TimerArmOutcome<Token> {
decision: TimerArmDecision<Token>,
}
pub struct TimerCancellationOutcome<Token> {
decision: TimerCancellationDecision<Token>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TimerArmDecision<Token> {
Armed {
token: Token,
},
Refused {
token: Token,
after: WakeAfter,
reason: TimerArmRefusal,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TimerCancellationDecision<Token> {
Cancelled {
token: Token,
},
Refused {
token: Token,
reason: TimerCancellationRefusal,
},
}
impl<Token> TimerArmOutcome<Token> {
pub fn into_decision(self) -> TimerArmDecision<Token> {
self.decision
}
}
impl<Token> TimerCancellationOutcome<Token> {
pub fn into_decision(self) -> TimerCancellationDecision<Token> {
self.decision
}
}
impl<'message, Token> TimerOut<'message, Token> {
pub fn into_arm_outcome(self) -> Result<TimerArmOutcome<Token>, Self> {
match self {
Self::Armed { token } => Ok(TimerArmOutcome {
decision: TimerArmDecision::Armed { token },
}),
Self::ArmRefused {
token,
after,
reason,
} => Ok(TimerArmOutcome {
decision: TimerArmDecision::Refused {
token,
after,
reason,
},
}),
Self::Elapsed { .. } | Self::Cancelled { .. } | Self::CancellationRefused { .. } => {
Err(self)
}
}
}
pub fn into_cancellation_outcome(self) -> Result<TimerCancellationOutcome<Token>, Self> {
match self {
Self::Cancelled { token } => Ok(TimerCancellationOutcome {
decision: TimerCancellationDecision::Cancelled { token },
}),
Self::CancellationRefused { token, reason } => Ok(TimerCancellationOutcome {
decision: TimerCancellationDecision::Refused { token, reason },
}),
Self::Armed { .. } | Self::Elapsed { .. } | Self::ArmRefused { .. } => Err(self),
}
}
}
#[cfg(test)]
mod tests;