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()),
}
}
}
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 Poll::Ready(result) = self.protocol.poll(waiter)
{
self.result = Some(result);
if 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()
}
}