use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
pub struct DtactSleep {
inner: tokio::time::Sleep,
}
impl DtactSleep {
#[must_use]
pub fn new(duration: Duration) -> Self {
Self {
inner: tokio::time::sleep(duration),
}
}
#[must_use]
pub fn until(deadline: Instant) -> Self {
Self {
inner: tokio::time::sleep_until(deadline.into()),
}
}
}
impl Future for DtactSleep {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
let inner = unsafe { self.map_unchecked_mut(|s| &mut s.inner) };
inner.poll(cx)
}
}
#[must_use]
pub fn sleep(duration: Duration) -> DtactSleep {
DtactSleep::new(duration)
}
pub struct DtactInterval {
inner: tokio::time::Interval,
}
impl DtactInterval {
#[must_use]
pub fn new(period: Duration) -> Self {
Self {
inner: tokio::time::interval(period),
}
}
pub async fn tick(&mut self) -> Instant {
self.inner.tick().await.into_std()
}
#[must_use]
pub fn missed_tick_behavior(&self) -> MissedTickBehavior {
self.inner.missed_tick_behavior()
}
pub fn set_missed_tick_behavior(&mut self, behavior: MissedTickBehavior) {
self.inner.set_missed_tick_behavior(behavior);
}
}
pub use tokio::time::MissedTickBehavior;
#[must_use]
pub fn interval(period: Duration) -> DtactInterval {
DtactInterval::new(period)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TimeoutError;
impl std::fmt::Display for TimeoutError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"dtact-timer: deadline elapsed before the future completed"
)
}
}
impl std::error::Error for TimeoutError {}
impl From<tokio::time::error::Elapsed> for TimeoutError {
fn from(_: tokio::time::error::Elapsed) -> Self {
Self
}
}
pub struct DtactTimeout<F> {
inner: tokio::time::Timeout<F>,
}
impl<F: Future> DtactTimeout<F> {
pub fn new(duration: Duration, inner: F) -> Self {
Self {
inner: tokio::time::timeout(duration, inner),
}
}
}
impl<F: Future> Future for DtactTimeout<F> {
type Output = Result<F::Output, TimeoutError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let inner = unsafe { self.map_unchecked_mut(|s| &mut s.inner) };
inner.poll(cx).map(|r| r.map_err(TimeoutError::from))
}
}
pub fn timeout<F: Future>(duration: Duration, fut: F) -> DtactTimeout<F> {
DtactTimeout::new(duration, fut)
}