use nb;
use void::Void;
use core::time::Duration;
use core::ops::Sub;
use core::convert::Into;
pub trait CheckedSub {
fn checked_sub_impl(self, rhs: Self) -> bool;
}
impl CheckedSub for u32 {
fn checked_sub_impl(self, rhs: u32) -> bool {
self.checked_sub(rhs).is_some()
}
}
impl CheckedSub for i32 {
fn checked_sub_impl(self, rhs: i32) -> bool {
self.checked_sub(rhs).is_some()
}
}
pub trait Timer
where
Self : Sized
{
type U : Sub<Output = Self::U> + Into<u32> + CheckedSub + Copy;
fn delay(&mut self, d: Duration);
fn delay_with_interrupt(&mut self, d: Duration) {
self.delay(d);
}
fn start(self) -> TimerInstant<Self>;
fn stop(self) -> Self;
fn has_wrapped(&mut self) -> bool;
fn limit_value(&self) -> Self::U;
fn get_current(&mut self) -> Self::U;
fn tick(&mut self) -> Duration;
}
pub struct TimerInstant<T>
where T : Timer
{
delay: T,
}
impl<T> TimerInstant<T>
where T : Timer
{
pub fn now(delay: T) -> Self {
TimerInstant {
delay,
}
}
pub fn wait(&mut self, d: Duration) -> nb::Result<(), Void> {
if self.elapsed() < d {
Err(nb::Error::WouldBlock)
} else {
Ok(())
}
}
pub fn elapsed(&mut self) -> Duration {
if self.delay.has_wrapped() {
panic!("Can not tell the elapse time as we have wrapped.")
}
let limit = self.delay.limit_value();
let current = self.delay.get_current();
if limit.checked_sub_impl(current) {
self.delay.tick() * (limit - current).into()
} else {
self.delay.tick() * (current - limit).into()
}
}
pub fn stop(self) -> T {
self.delay.stop()
}
}