#![allow(non_snake_case)]
use crate::prelude::*;
macro_rules! expr {
($x:expr) => {
$x
};
}
macro_rules! tuple_index {
($tuple:expr, $idx:tt) => {
expr!($tuple.$idx)
};
}
macro_rules! parallel_new_rhs {
($opts:ident, ) => {
()
};
($opts:ident, $ts:ident) => {
$ts::new($ts, $opts)
};
($opts:ident, $ts:ident, $($remainder:ident),+) => {
parallel(move || $ts::new($ts, $opts), move || parallel_new_rhs!($opts, $($remainder),*), $opts)
}
}
macro_rules! parallel_read_rhs {
($opts: ident) => {
()
};
($opts: ident, $ts:ident) => {
$ts::read($ts, $opts)
};
($opts: ident, $ts:ident, $($remainder:ident),+) => {
parallel(move || $ts::read($ts, $opts), move || parallel_read_rhs!($opts, $($remainder),*), $opts)
}
}
macro_rules! parallel_lhs {
() => {
()
};
($ts:ident) => {
$ts
};
($ts:ident, $($remainder:ident),+) => {
($ts, parallel_lhs!($($remainder),*))
}
}
macro_rules! parallel_new {
($opts:ident, $($ts:ident),*) => {
let parallel_lhs!($($ts),*) = parallel_new_rhs!($opts, $($ts),*);
};
}
macro_rules! parallel_read {
($opts:ident, $($ts:ident),*) => {
let parallel_lhs!($($ts),*) = parallel_read_rhs!($opts, $($ts),*);
};
}
macro_rules! impl_tuple {
($count:expr, $trid:expr, $taid:expr, $($ts:ident, $ti:tt,)+) => {
#[cfg(feature = "write")]
impl <'a, $($ts: Writable<'a>),+> Writable<'a> for ($($ts),+) {
type WriterArray=($($ts::WriterArray),+);
fn write_root<'b: 'a>(&'b self, stream: &mut impl WriterStream) -> RootTypeId {
$(
stream.write_with_id(|stream| tuple_index!(self, $ti).write_root(stream));
)+
$trid
}
}
#[cfg(feature = "write")]
impl<'a, $($ts: WriterArray<'a>),+> WriterArray<'a> for ($($ts),+) {
type Write=($($ts::Write),+);
fn buffer<'b: 'a>(&mut self, value: &'b Self::Write) {
$(
tuple_index!(self, $ti).buffer(&tuple_index!(value, $ti));
)+
}
fn flush(self, stream: &mut impl WriterStream) -> ArrayTypeId {
let ($($ts,)+) = self;
$(
stream.write_with_id(|stream|
$ts.flush(stream)
);
)+
$taid
}
}
#[cfg(feature = "read")]
impl <$($ts: Readable + Send),+> Readable for ($($ts),+) {
type ReaderArray=($($ts::ReaderArray),+);
fn read(sticks: DynRootBranch<'_>, options: &impl DecodeOptions) -> ReadResult<Self> {
match sticks {
DynRootBranch::Tuple { mut fields } => {
if fields.len() != $count {
return Err(ReadError::SchemaMismatch)
}
let mut fields = fields.drain(..);
$(
let $ts = fields.next().unwrap();
)+
parallel_read!(options, $($ts),*);
Ok(($($ts?),*))
},
_ => Err(ReadError::SchemaMismatch),
}
}
}
#[cfg(feature = "read")]
impl <$($ts: ReaderArray),+> ReaderArray for ($($ts),+) {
type Read=($($ts::Read),+);
fn new(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> ReadResult<Self> {
match sticks {
DynArrayBranch::Tuple { mut fields } => {
if fields.len() != $count {
return Err(ReadError::SchemaMismatch)
}
let mut fields = fields.drain(..);
$(
let $ts = fields.next().unwrap();
)+
parallel_new!(options, $($ts),*);
Ok(($($ts?),*))
},
_ => Err(ReadError::SchemaMismatch)
}
}
fn read_next(&mut self) -> Self::Read {
($(
tuple_index!(self, $ti).read_next(),
)+)
}
}
};
}
impl_tuple!(2, RootTypeId::Tuple2, ArrayTypeId::Tuple2, T0, 0, T1, 1,);
impl_tuple!(3, RootTypeId::Tuple3, ArrayTypeId::Tuple3, T0, 0, T1, 1, T2, 2,);
impl_tuple!(4, RootTypeId::Tuple4, ArrayTypeId::Tuple4, T0, 0, T1, 1, T2, 2, T3, 3,);
impl_tuple!(5, RootTypeId::Tuple5, ArrayTypeId::Tuple5, T0, 0, T1, 1, T2, 2, T3, 3, T4, 4,);
impl_tuple!(6, RootTypeId::Tuple6, ArrayTypeId::Tuple6, T0, 0, T1, 1, T2, 2, T3, 3, T4, 4, T5, 5,);