use std::task::Poll;
use crate::Error;
use crate::time::{Clock, Instant};
#[must_use = "the session makes no progress unless its driver is polled"]
pub struct Driver<S: crate::transport::poll::Session> {
state: State<S>,
clock: Clock,
}
pub(crate) enum Protocol<S: crate::transport::poll::Session> {
Lite(Box<crate::lite::Driver<S>>),
Ietf(crate::util::MaybeSendBox<'static, Result<(), Error>>),
}
pub(crate) struct State<S: crate::transport::poll::Session> {
pub(crate) protocol: Protocol<S>,
pub(crate) supervisor: Option<crate::session::Supervisor<S>>,
pub(crate) result: Option<Result<(), Error>>,
}
impl<S: crate::transport::poll::Session> Driver<S> {
pub(crate) fn new(clock: Clock, state: State<S>) -> Self {
Self { state, clock }
}
pub fn poll(&mut self, now: Instant, waiter: &kio::Waiter) -> Result<Option<Instant>, Error> {
self.clock.advance(now);
match self.state.poll(waiter) {
Poll::Ready(Ok(())) => Err(Error::Closed),
Poll::Ready(Err(err)) => Err(err),
Poll::Pending => Ok(self.clock.timeout()),
}
}
}
impl<S: crate::transport::poll::Session> Protocol<S> {
fn poll(&mut self, waiter: &kio::Waiter) -> Poll<Result<(), Error>> {
match self {
Self::Lite(driver) => driver.poll(waiter),
Self::Ietf(driver) => waiter.poll_future(driver.as_mut()),
}
}
fn drained(&self) -> bool {
match self {
Self::Lite(driver) => driver.drained(),
Self::Ietf(_) => true,
}
}
}
impl<S: crate::transport::poll::Session> State<S> {
fn poll(&mut self, waiter: &kio::Waiter) -> Poll<Result<(), Error>> {
if let Some(supervisor) = &mut self.supervisor
&& supervisor.poll(waiter).is_ready()
{
self.supervisor = None;
}
if self.result.is_none() {
let closed = match self.protocol.poll(waiter) {
Poll::Ready(result) => {
self.result = Some(result);
true
}
Poll::Pending => self
.supervisor
.as_mut()
.is_some_and(|supervisor| supervisor.poll_drain(self.protocol.drained(), waiter)),
};
if closed
&& let Some(supervisor) = &mut self.supervisor
&& supervisor.poll(waiter).is_ready()
{
self.supervisor = None;
}
}
match (&self.result, &self.supervisor) {
(Some(result), None) => Poll::Ready(result.clone()),
_ => Poll::Pending,
}
}
}
impl<S: crate::transport::poll::Session> crate::time::Driver for Driver<S> {
fn poll(&mut self, now: Instant, waiter: &kio::Waiter) -> Result<Option<Instant>, Error> {
self.poll(now, waiter)
}
}
impl<S: crate::transport::poll::Session> std::fmt::Debug for Driver<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Driver")
.field("done", &self.state.result.is_some())
.finish()
}
}