use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
time::Duration,
};
use s2n_quic_core::time::{self, Timestamp};
use tokio::time::{sleep_until, Instant, Sleep};
#[derive(Clone, Debug)]
pub struct Clock(Instant);
impl Default for Clock {
fn default() -> Self {
Self::new()
}
}
impl Clock {
pub fn new() -> Self {
Self(Instant::now())
}
}
impl time::Clock for Clock {
#[inline]
fn get_time(&self) -> time::Timestamp {
let duration = self.0.elapsed();
unsafe {
time::Timestamp::from_duration(duration)
}
}
}
impl time::ClockWithTimer for Clock {
type Timer = Timer;
#[inline]
fn timer(&self) -> Timer {
Timer::new(self.clone())
}
}
#[derive(Debug)]
pub struct Timer {
clock: Clock,
target: Option<Instant>,
sleep: Pin<Box<Sleep>>,
}
impl Timer {
fn new(clock: Clock) -> Self {
const INITIAL_TIMEOUT: Duration = Duration::from_secs(1);
let target = clock.0 + INITIAL_TIMEOUT;
let sleep = Box::pin(sleep_until(target));
Self {
clock,
target: Some(target),
sleep,
}
}
}
impl time::clock::Timer for Timer {
#[inline]
fn poll_ready(&mut self, cx: &mut Context) -> Poll<()> {
if self.target.is_none() {
return Poll::Pending;
}
let res = self.sleep.as_mut().poll(cx);
if res.is_ready() {
self.target = None;
}
res
}
#[inline]
fn update(&mut self, timestamp: Timestamp) {
let delay = unsafe {
timestamp.as_duration()
};
let delay = Duration::from_millis(delay.as_millis() as u64);
let next_time = self.clock.0 + delay;
if Some(next_time) == self.target {
return;
}
self.sleep.as_mut().reset(next_time);
self.target = Some(next_time);
}
}