use std::{fmt, hash::Hash, time::SystemTime};
#[cfg(feature = "chrono")]
#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
pub mod chrono;
pub trait State {
type Id: Hash + Clone + Eq;
fn id(&self) -> &Self::Id;
fn trigger(self);
}
pub trait WallClockTimer {
type Id: Hash + Clone + Eq + Ord;
type State: State<Id = Self::Id>;
type Error: std::error::Error + Send + Sync + 'static;
fn schedule_at(&mut self, deadline: SystemTime, state: Self::State) -> Result<(), Self::Error>;
fn cancel(&mut self, id: Self::Id) -> Result<(), Self::Error>;
}
pub struct ClosureState<I> {
id: I,
action: Box<dyn FnOnce(I) + Send + 'static>,
}
impl<I> ClosureState<I> {
pub fn new<F>(id: I, action: F) -> Self
where
F: FnOnce(I) + Send + 'static,
{
ClosureState {
id,
action: Box::new(action),
}
}
}
impl<I> State for ClosureState<I>
where
I: Hash + Clone + Eq,
{
type Id = I;
fn id(&self) -> &Self::Id {
&self.id
}
fn trigger(self) {
(self.action)(self.id)
}
}
impl<I> fmt::Debug for ClosureState<I>
where
I: Hash + Clone + Eq + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ClosureState(id={:?}, action=<function>)", self.id)
}
}
pub trait ClosureTimer: WallClockTimer {
fn schedule_action_at<F>(
&mut self,
id: Self::Id,
deadline: std::time::SystemTime,
action: F,
) -> Result<(), Self::Error>
where
F: FnOnce(Self::Id) + Send + 'static;
}
impl<I, T> ClosureTimer for T
where
I: Hash + Clone + Eq,
T: WallClockTimer<Id = I, State = ClosureState<I>>,
{
fn schedule_action_at<F>(
&mut self,
id: Self::Id,
deadline: std::time::SystemTime,
action: F,
) -> Result<(), Self::Error>
where
F: FnOnce(Self::Id) + Send + 'static,
{
self.schedule_at(deadline, ClosureState::new(id, action))
}
}
#[cfg(feature = "uuid")]
pub type UuidClosureTimerRef = crate::thread_timer::ClosureTimerRef<uuid::Uuid>;