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, TryFuture, TryZipFuture};
use super::base::{Join, JoinTuple};
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
pub fn try_zip<T: TryZipTuple>(futures: T) -> TryZip<T> {
TryZip {
inner: Join::new(futures.into_tuple()),
_correct_debug_bounds: PhantomData,
}
}
pin_project! {
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
#[derive(Debug)]
pub struct TryZip<T: TryZipTuple> {
#[pin]
inner: Join<T::JoinTuple>,
_correct_debug_bounds: PhantomData<(T::Futures, T::Error)>,
}
}
impl<T: TryZipTuple> CompletionFuture for TryZip<T> {
type Output = Result<<T::JoinTuple as JoinTuple>::Output, <T::JoinTuple as JoinTuple>::Break>;
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) => Ok(val),
ControlFlow::Break(e) => Err(e),
})
}
unsafe fn poll_cancel(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
self.project().inner.poll_cancel(cx)
}
}
pub trait TryZipTuple {
type JoinTuple: JoinTuple<Futures = Self::Futures, Break = Self::Error>;
fn into_tuple(self) -> Self::JoinTuple;
type Futures;
type Error;
}
macro_rules! impl_try_zip_tuple {
($($param:ident),*) => {
impl<Error, $($param,)*> TryZipTuple for ($($param,)*)
where
$($param: TryFuture<Error = Error>,)*
{
type JoinTuple = ($(TryZipFuture<$param>,)*);
fn into_tuple(self) -> Self::JoinTuple {
let ($($param,)*) = self;
($(TryZipFuture::new($param),)*)
}
type Futures = <Self::JoinTuple as JoinTuple>::Futures;
type Error = <Self::JoinTuple as JoinTuple>::Break;
}
}
}
apply_on_tuples!(impl_try_zip_tuple!);