graphql-ws-client 0.13.0

A graphql over websockets client
Documentation
use std::{future::Future, task::Poll};

use futures_lite::{FutureExt, future};

/// A future that runs a long running producer future while also polling a future
/// that should be reading a stream generated by that producer future.
///
/// This will resolve to Some(Out, future::Boxed<()>) if the reader resolves,
/// and None if the producer fails.
#[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),
    }
}