use std::{
ops::ControlFlow,
pin::Pin,
task::{Context, Poll},
};
use futures::Stream;
pub trait Pollable<'a, E: ?Sized, EMut: ?Sized> {
type Progress;
fn poll_progress(
self: Pin<&mut Self>,
ext: &'a E,
ext_mut: &mut EMut,
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>>;
}
pub trait PollProxy<'a, P, E: ?Sized, EMut: ?Sized>: sealed::Sealed {
type Progress;
fn poll_progress(
state: Pin<&mut P>,
ext: &'a E,
ext_mut: &mut EMut,
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>>;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct PollFuture;
impl sealed::Sealed for PollFuture {}
impl<'a, F: Future> PollProxy<'a, F, (), ()> for PollFuture {
type Progress = F::Output;
fn poll_progress(
state: Pin<&mut F>,
_: &'a (),
_: &mut (),
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
state.poll(cx).map(Some).map(ControlFlow::Break)
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct PollStream;
impl sealed::Sealed for PollStream {}
impl<'a, S: Stream> PollProxy<'a, S, (), ()> for PollStream {
type Progress = S::Item;
fn poll_progress(
state: Pin<&mut S>,
_: &'a (),
_: &mut (),
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
state.poll_next(cx).map(|opt| {
opt.map(ControlFlow::Continue)
.unwrap_or(ControlFlow::Break(None))
})
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct PollDirect;
impl sealed::Sealed for PollDirect {}
impl<'a, P, E, EMut> PollProxy<'a, P, E, EMut> for PollDirect
where
P: Pollable<'a, E, EMut>,
E: ?Sized,
EMut: ?Sized,
{
type Progress = P::Progress;
fn poll_progress(
state: Pin<&mut P>,
ext: &'a E,
ext_mut: &mut EMut,
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
state.poll_progress(ext, ext_mut, cx)
}
}
mod sealed {
pub trait Sealed {}
}