use futures_core::Stream; use std::{ pin::Pin, task::{Context, Poll}, }; use tokio::io::{AsyncRead, ReadBuf}; pin_project_lite::pin_project! { #[project = EitherProj] #[project_replace = EitherProjReplace] pub(crate) enum Either { Left { #[pin] left: Left, }, Right { #[pin] right: Right, }, } } impl Either { pub(crate) fn left(left: L) -> Self { Either::Left { left } } pub(crate) fn right(right: R) -> Self { Either::Right { right } } } impl AsyncRead for Either where Left: AsyncRead, Right: AsyncRead, { fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll> { let this = self.as_mut().project(); match this { EitherProj::Left { left } => left.poll_read(cx, buf), EitherProj::Right { right } => right.poll_read(cx, buf), } } } impl Stream for Either where Left: Stream::Item>, Right: Stream, { type Item = ::Item; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.as_mut().project(); match this { EitherProj::Left { left } => left.poll_next(cx), EitherProj::Right { right } => right.poll_next(cx), } } }