use std::{
marker::PhantomData,
ops::ControlFlow,
pin::Pin,
task::{Context, Poll},
};
use futures::Stream;
pub trait PollStrategy {
type Pollable;
}
pub struct PollAsFuture<F>(PhantomData<fn() -> F>);
impl<F: Future> PollStrategy for PollAsFuture<F> {
type Pollable = F;
}
pub struct PollAsStream<S>(PhantomData<fn() -> S>);
impl<S: Stream> PollStrategy for PollAsStream<S> {
type Pollable = S;
}
pub trait PollWith<'a, E: ?Sized, EMut: ?Sized>: PollStrategy {
type Progress;
fn poll_progress(
state: Pin<&mut Self::Pollable>,
ext: &'a E,
ext_mut: &mut EMut,
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>>;
}
impl<'a, F: Future> PollWith<'a, (), ()> for PollAsFuture<F> {
type Progress = F::Output;
fn poll_progress(
state: Pin<&mut Self::Pollable>,
_: &'a (),
_: &mut (),
cx: &mut Context<'_>,
) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
state.poll(cx).map(Some).map(ControlFlow::Break)
}
}
impl<'a, S: Stream> PollWith<'a, (), ()> for PollAsStream<S> {
type Progress = S::Item;
fn poll_progress(
state: Pin<&mut Self::Pollable>,
_: &'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))
})
}
}