use core::marker::{PhantomData, Tuple};
use tuple_split::TupleSplitInto;
use tupleops::{TupleConcat, ConcatTuples};
#[cfg(feature = "async")]
use crate::JoinedPair;
#[cfg(feature = "async")]
use core::ops::{AsyncFnOnce, AsyncFnMut, AsyncFn};
pub struct ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple
{
pub left: LF,
pub right: RF,
marker: PhantomData<(LX, RX)>
}
impl<LX, RX, LF, RF> ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple
{
pub const fn new(left: LF, right: RF) -> Self
{
Self {
left,
right,
marker: PhantomData
}
}
}
impl<LX, RX, LF, RF> FnOnce<ConcatTuples<LX, RX>> for ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple,
LF: FnOnce<LX>,
RF: FnOnce<RX>,
(LX, RX): TupleConcat<LX, RX, Type: Tuple>,
ConcatTuples<LX, RX>: TupleSplitInto<LX, RX>
{
type Output = (LF::Output, RF::Output);
extern "rust-call" fn call_once(self, args: ConcatTuples<LX, RX>) -> Self::Output
{
let (args_left, args_right) = tuple_split::split_tuple_into(args);
(self.left.call_once(args_left), self.right.call_once(args_right))
}
}
impl<LX, RX, LF, RF> FnMut<ConcatTuples<LX, RX>> for ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple,
LF: FnMut<LX>,
RF: FnMut<RX>,
(LX, RX): TupleConcat<LX, RX, Type: Tuple>,
ConcatTuples<LX, RX>: TupleSplitInto<LX, RX>
{
extern "rust-call" fn call_mut(&mut self, args: ConcatTuples<LX, RX>) -> Self::Output
{
let (args_left, args_right) = tuple_split::split_tuple_into(args);
(self.left.call_mut(args_left), self.right.call_mut(args_right))
}
}
impl<LX, RX, LF, RF> Fn<ConcatTuples<LX, RX>> for ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple,
LF: Fn<LX>,
RF: Fn<RX>,
(LX, RX): TupleConcat<LX, RX, Type: Tuple>,
ConcatTuples<LX, RX>: TupleSplitInto<LX, RX>
{
extern "rust-call" fn call(&self, args: ConcatTuples<LX, RX>) -> Self::Output
{
let (args_left, args_right) = tuple_split::split_tuple_into(args);
(self.left.call(args_left), self.right.call(args_right))
}
}
#[cfg(feature = "async")]
impl<LX, RX, LF, RF> AsyncFnOnce<ConcatTuples<LX, RX>> for ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple,
LF: AsyncFnOnce<LX>,
RF: AsyncFnOnce<RX>,
(LX, RX): TupleConcat<LX, RX, Type: Tuple>,
ConcatTuples<LX, RX>: TupleSplitInto<LX, RX>
{
type Output = (LF::Output, RF::Output);
type CallOnceFuture = JoinedPair<<LF as AsyncFnOnce<LX>>::CallOnceFuture, <RF as AsyncFnOnce<RX>>::CallOnceFuture>;
extern "rust-call" fn async_call_once(self, args: ConcatTuples<LX, RX>) -> Self::CallOnceFuture
{
let (args_left, args_right) = tuple_split::split_tuple_into(args);
JoinedPair::new(
self.left.async_call_once(args_left),
self.right.async_call_once(args_right)
)
}
}
#[cfg(feature = "async")]
impl<LX, RX, LF, RF> AsyncFnMut<ConcatTuples<LX, RX>> for ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple,
LF: AsyncFnMut<LX>,
RF: AsyncFnMut<RX>,
(LX, RX): TupleConcat<LX, RX, Type: Tuple>,
ConcatTuples<LX, RX>: TupleSplitInto<LX, RX>
{
type CallRefFuture<'a> = JoinedPair<<LF as AsyncFnMut<LX>>::CallRefFuture<'a>, <RF as AsyncFnMut<RX>>::CallRefFuture<'a>>
where
Self: 'a;
extern "rust-call" fn async_call_mut(&mut self, args: ConcatTuples<LX, RX>) -> Self::CallRefFuture<'_>
{
let (args_left, args_right) = tuple_split::split_tuple_into(args);
JoinedPair::new(
self.left.async_call_mut(args_left),
self.right.async_call_mut(args_right)
)
}
}
#[cfg(feature = "async")]
impl<LX, RX, LF, RF> AsyncFn<ConcatTuples<LX, RX>> for ZippedFn<LX, RX, LF, RF>
where
LX: Tuple,
RX: Tuple,
LF: AsyncFn<LX>,
RF: AsyncFn<RX>,
(LX, RX): TupleConcat<LX, RX, Type: Tuple>,
ConcatTuples<LX, RX>: TupleSplitInto<LX, RX>
{
extern "rust-call" fn async_call(&self, args: ConcatTuples<LX, RX>) -> Self::CallRefFuture<'_>
{
let (args_left, args_right) = tuple_split::split_tuple_into(args);
JoinedPair::new(
self.left.async_call(args_left),
self.right.async_call(args_right)
)
}
}