use core::convert::Infallible;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use completion_core::CompletionFuture;
use pin_project_lite::pin_project;
use super::super::{ControlFlow, ZipFuture};
use super::base::{Join, JoinTuple};
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub fn zip<T: ZipTuple>(futures: T) -> Zip<T> {
Zip {
inner: Join::new(futures.into_tuple()),
_correct_debug_bounds: PhantomData,
}
}
pin_project! {
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
#[derive(Debug)]
pub struct Zip<T: ZipTuple> {
#[pin]
inner: Join<T::JoinTuple>,
_correct_debug_bounds: PhantomData<T::Futures>,
}
}
impl<T: ZipTuple> CompletionFuture for Zip<T> {
type Output = <T::JoinTuple as JoinTuple>::Output;
unsafe fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.project().inner.poll(cx).map(|flow| match flow {
ControlFlow::Continue(val) => val,
ControlFlow::Break(no) => match no {},
})
}
unsafe fn poll_cancel(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
self.project().inner.poll_cancel(cx)
}
}
pub trait ZipTuple {
type JoinTuple: JoinTuple<Futures = Self::Futures, Break = Infallible>;
fn into_tuple(self) -> Self::JoinTuple;
type Futures;
}
macro_rules! impl_zip_tuple {
($($param:ident),*) => {
impl<$($param,)*> ZipTuple for ($($param,)*)
where
$($param: CompletionFuture,)*
{
type JoinTuple = ($(ZipFuture<$param>,)*);
fn into_tuple(self) -> Self::JoinTuple {
let ($($param,)*) = self;
($(ZipFuture::new($param),)*)
}
type Futures = <Self::JoinTuple as JoinTuple>::Futures;
}
}
}
apply_on_tuples!(impl_zip_tuple!);