use crate::{tick, FREQ};
use alloc::boxed::Box;
use core::pin::Pin;
use core::task::{Context, Poll};
pub struct Timeout<'bemly_, Content> {
future: Pin<Box<dyn Future<Output = Content> + 'bemly_>>,
deadline: u64,
}
impl<'bemly_, Content> Timeout<'bemly_, Content> {
#[inline]
pub fn new(future: impl Future<Output = Content> + 'bemly_, ticks: u64) -> Self {
Self { future: Box::pin(future), deadline: tick().saturating_add(ticks) }
}
#[inline(always)]
pub fn new_pin(future: Pin<Box<dyn Future<Output = Content> + 'bemly_>>, ticks: u64) -> Self {
Self { future, deadline: tick().saturating_add(ticks) }
}
}
impl<'bemly_, Content> Future for Timeout<'bemly_, Content> {
type Output = Result<Content, ()>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
if tick() >= self.deadline { return Poll::Ready(Err(())) }
match self.future.as_mut().poll(cx) {
Poll::Ready(val) => Poll::Ready(Ok(val)),
Poll::Pending => Poll::Pending,
}
}
}
pub trait _Timeout<'bemly_>: Future + Sized {
fn timeout(self, duration_ticks: u64) -> Timeout<'bemly_, Self::Output> where Self: 'bemly_ {
Timeout::new(self, duration_ticks)
}
}
impl<F: Future + Sized> _Timeout<'_> for F {}
#[derive(Debug)]
pub struct WaitTimer(u64);
impl WaitTimer {
#[inline(always)]
pub fn until(deadline: u64) -> Self { Self(deadline) }
#[inline(always)]
pub fn after(ticks_to_wait: u64) -> Self { Self(tick().wrapping_add(ticks_to_wait)) }
#[inline(always)]
pub fn is_expired(&self) -> bool { tick() >= self.0 }
#[inline(always)]
pub fn from_year(y: u64) -> Self { Self::after(y.saturating_mul(FREQ.hz().saturating_mul(31536000))) }
#[inline(always)]
pub fn from_month(m: u64) -> Self { Self::after(m.saturating_mul(FREQ.hz() * 2592000)) }
#[inline(always)]
pub fn from_week(w: u64) -> Self { Self::after(w.saturating_mul(FREQ.hz() * 604800)) }
#[inline(always)]
pub fn from_day(d: u64) -> Self { Self::after(d.saturating_mul(FREQ.hz() * 86400)) }
#[inline(always)]
pub fn from_hour(h: u64) -> Self { Self::after(h.saturating_mul(FREQ.hz() * 3600)) }
#[inline(always)]
pub fn from_min(min: u64) -> Self { Self::after(min.saturating_mul(FREQ.hz() * 60)) }
#[inline(always)]
pub fn from_s(hz: u64) -> Self { Self::after(hz.saturating_mul(FREQ.hz())) }
#[inline(always)]
pub fn from_ms(ms: u64) -> Self { Self::after(ms.saturating_mul(FREQ.ms())) }
#[inline(always)]
pub fn from_us(us: u64) -> Self { Self::after(us.saturating_mul(FREQ.us())) }
#[inline(always)]
pub fn from_ns(ns: u64) -> Self { Self::after(ns.saturating_mul(FREQ.ns())) }
#[inline(always)]
pub fn from_ps(ps: u64) -> Self { Self::after(ps.saturating_mul(FREQ.ps())) }
#[inline(always)]
pub fn from_fps(fps: u64) -> Self { Self::after(FREQ.hz() / fps.max(1)) }
}
impl Future for WaitTimer {
type Output = ();
fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> {
if self.is_expired() { Poll::Ready(()) } else { Poll::Pending }
}
}
pub trait _WaitTimer: Into<u64> + Sized {
#[inline(always)]
fn year(self) -> WaitTimer { WaitTimer::from_year(self.into()) }
#[inline(always)]
fn month(self) -> WaitTimer { WaitTimer::from_month(self.into()) }
#[inline(always)]
fn week(self) -> WaitTimer { WaitTimer::from_week(self.into()) }
#[inline(always)]
fn day(self) -> WaitTimer { WaitTimer::from_day(self.into()) }
#[inline(always)]
fn hour(self) -> WaitTimer { WaitTimer::from_hour(self.into()) }
#[inline(always)]
fn mins(self) -> WaitTimer { WaitTimer::from_min(self.into()) }
#[inline(always)]
fn s(self) -> WaitTimer { WaitTimer::from_s(self.into()) }
#[inline(always)]
fn hz(self) -> WaitTimer { WaitTimer::from_s(self.into()) }
#[inline(always)]
fn ms(self) -> WaitTimer { WaitTimer::from_ms(self.into()) }
#[inline(always)]
fn us(self) -> WaitTimer { WaitTimer::from_us(self.into()) }
#[inline(always)]
fn ns(self) -> WaitTimer { WaitTimer::from_ns(self.into()) }
#[inline(always)]
fn ps(self) -> WaitTimer { WaitTimer::from_ps(self.into()) }
#[inline(always)]
fn fps(self) -> WaitTimer { WaitTimer::from_fps(self.into()) }
}
impl _WaitTimer for u64 {}