use std::{future::Future, task::Poll};
use futures_lite::{FutureExt, future};
#[pin_project::pin_project]
pub struct ProductionFuture<ReadFut, Out>
where
ReadFut: Future<Output = Out>,
{
#[pin]
reader: ReadFut,
pub producer: Option<future::Boxed<()>>,
}
impl<ReadFut, Out> Future for ProductionFuture<ReadFut, Out>
where
ReadFut: Future<Output = Out>,
{
type Output = Option<(Out, future::Boxed<()>)>;
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
let this = self.project();
let Some(producer) = this.producer else {
return Poll::Ready(None);
};
match this.reader.poll(cx) {
Poll::Ready(read_output) => {
return Poll::Ready(Some((read_output, this.producer.take().unwrap())));
}
Poll::Pending => {}
}
if producer.poll(cx).is_ready() {
return Poll::Ready(None);
}
Poll::Pending
}
}
pub fn read_from_producer<ReadFut, Out>(
reader: ReadFut,
producer: future::Boxed<()>,
) -> ProductionFuture<ReadFut, Out>
where
ReadFut: Future<Output = Out>,
{
ProductionFuture {
reader,
producer: Some(producer),
}
}