use crate::utils::Cancellable;
use futures_lite::stream::Stream;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
pub trait AsyncTime {
type Interval: TimeInterval;
fn sleep(d: Duration) -> impl Future + Send;
fn interval(d: Duration) -> Self::Interval;
#[inline]
fn timeout<F>(d: Duration, func: F) -> impl Future<Output = Result<F::Output, ()>> + Send
where
F: Future + Send,
{
Cancellable::new(func, Self::sleep(d))
}
}
pub trait TimeInterval: Unpin + Send {
fn poll_tick(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Instant>;
fn tick<'a>(&'a mut self) -> TickFuture<'a, Self>
where
Self: Sized,
{
TickFuture::new(self)
}
#[inline(always)]
fn into_stream(self) -> IntervalStream<Self>
where
Self: Sized,
{
IntervalStream::new(self)
}
}
pub struct IntervalStream<T: TimeInterval> {
interval: T,
}
impl<T: TimeInterval> IntervalStream<T> {
pub fn new(interval: T) -> Self {
Self { interval }
}
}
impl<T: TimeInterval> Stream for IntervalStream<T> {
type Item = Instant;
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
unsafe { Pin::new_unchecked(&mut self.interval).poll_tick(ctx).map(Some) }
}
}
pub struct TickFuture<'a, T: TimeInterval> {
interval: &'a mut T,
}
impl<'a, T: TimeInterval> TickFuture<'a, T> {
pub fn new(interval: &'a mut T) -> Self {
Self { interval }
}
}
impl<'a, T: TimeInterval> Future for TickFuture<'a, T> {
type Output = Instant;
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
unsafe { Pin::new_unchecked(&mut *self.interval).poll_tick(ctx) }
}
}