use std::iter::Zip;
use crate::{sequence::PlainCollection, *};
#[derive(
ListHashes, Topological, Tagged, Size, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord,
)]
pub struct TupleOfArrays<A, B>(A, B);
impl<A: ByteOrd + Size, B: ByteOrd> ByteOrd for TupleOfArrays<A, B> {
fn bytes_cmp(&self, other: &Self) -> Ordering {
self.0
.bytes_cmp(&other.0)
.then_with(|| self.1.bytes_cmp(&other.1))
}
}
impl<A: ToOutput, B: ToOutput> ToOutput for TupleOfArrays<A, B> {
fn to_output(&self, output: &mut impl crate::Output) {
self.0.to_output(output);
self.1.to_output(output);
}
}
pub fn try_divide(n: usize, k: usize) -> crate::Result<usize> {
if !n.is_multiple_of(k) {
return Err(crate::error_parse!("doesn't divide evenly"));
}
n.checked_div(k)
.ok_or_else(|| crate::error_parse!("division failed"))
}
impl<
A: Parse<I> + PlainCollection<Item = Ae>,
B: Parse<I> + PlainCollection<Item = Be>,
I: ParseInput,
Ae: Size,
Be: Size,
> Parse<I> for TupleOfArrays<A, B>
{
fn parse(input: I) -> crate::Result<Self> {
let (mut input, n) = input.remaining()?;
let n = try_divide(n, Ae::SIZE + Be::SIZE)? * Ae::SIZE;
Ok(Self(input.split_parse(n)?, input.parse()?))
}
}
impl<A: IntoIterator, B: IntoIterator> IntoIterator for TupleOfArrays<A, B> {
type Item = (A::Item, B::Item);
type IntoIter = Zip<A::IntoIter, B::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter().zip(self.1)
}
}
impl<'a, A, B> IntoIterator for &'a TupleOfArrays<A, B>
where
&'a A: IntoIterator,
&'a B: IntoIterator,
{
type Item = (<&'a A as IntoIterator>::Item, <&'a B as IntoIterator>::Item);
type IntoIter = Zip<<&'a A as IntoIterator>::IntoIter, <&'a B as IntoIterator>::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter().zip(&self.1)
}
}
impl<'a, A, B> IntoIterator for &'a mut TupleOfArrays<A, B>
where
&'a mut A: IntoIterator,
&'a mut B: IntoIterator,
{
type Item = (
<&'a mut A as IntoIterator>::Item,
<&'a mut B as IntoIterator>::Item,
);
type IntoIter =
Zip<<&'a mut A as IntoIterator>::IntoIter, <&'a mut B as IntoIterator>::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter().zip(&mut self.1)
}
}
impl<A: PlainCollection, B: PlainCollection> PlainCollection for TupleOfArrays<A, B> {}
impl<A: Extend<L>, B: Extend<R>, L, R> Extend<(L, R)> for TupleOfArrays<A, B> {
fn extend<T: IntoIterator<Item = (L, R)>>(&mut self, iter: T) {
let (a, b): (Vec<_>, Vec<_>) = iter.into_iter().collect();
self.0.extend(a);
self.1.extend(b);
}
}
impl<A: FromIterator<L>, B: FromIterator<R>, L, R> FromIterator<(L, R)> for TupleOfArrays<A, B> {
fn from_iter<T: IntoIterator<Item = (L, R)>>(iter: T) -> Self {
let (a, b): (Vec<_>, Vec<_>) = iter.into_iter().collect();
Self(a.into_iter().collect(), b.into_iter().collect())
}
}