termit 0.7.0

Terminal UI over crossterm
Documentation
use futures_lite::prelude::*;
use futures_lite::stream::Fuse;
use std::pin::Pin;
use std::task::{Context, Poll};

/// A stream that merges two other streams into a single stream.
///
/// This `struct` is created by the [`merge`] method on [`Stream`]. See its
/// documentation for more.
///
/// [`merge`]: trait.Stream.html#method.merge
/// [`Stream`]: trait.Stream.html
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[derive(Debug)]
pub(crate) struct Merge<L, R> {
    left: Pin<Box<Fuse<L>>>,
    right: Pin<Box<Fuse<R>>>,
    alt: bool,
}

impl<L: Stream, R: Stream> Merge<L, R> {
    pub(crate) fn new(left: L, right: R) -> Self {
        Self {
            left: Box::pin(left.fuse()),
            right: Box::pin(right.fuse()),
            alt: false,
        }
    }
}

impl<L, R, T> Stream for Merge<L, R>
where
    L: Stream<Item = T>,
    R: Stream<Item = T>,
{
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.alt = !self.alt;
        if self.alt {
            match self.left.as_mut().poll_next(cx) {
                Poll::Ready(None) => self.right.as_mut().poll_next(cx),
                Poll::Ready(item) => Poll::Ready(item),
                Poll::Pending => match self.right.as_mut().poll_next(cx) {
                    Poll::Ready(None) | Poll::Pending => Poll::Pending,
                    Poll::Ready(item) => Poll::Ready(item),
                },
            }
        } else {
            match self.right.as_mut().poll_next(cx) {
                Poll::Ready(None) => self.left.as_mut().poll_next(cx),
                Poll::Ready(item) => Poll::Ready(item),
                Poll::Pending => match self.left.as_mut().poll_next(cx) {
                    Poll::Ready(None) | Poll::Pending => Poll::Pending,
                    Poll::Ready(item) => Poll::Ready(item),
                },
            }
        }
    }
}