use std::cmp::Ordering;
use std::mem::take;
use crate::vendor::rle::{HasLength, SplitableSpan};
#[derive(Clone, Debug)]
pub(crate) enum Remainder<A, B> {
Nothing,
SomeA(A),
SomeB(B),
}
impl<A, B> Default for Remainder<A, B> {
fn default() -> Self { Remainder::Nothing }
}
impl<A, B> Remainder<A, B> {
pub(crate) fn take_from_iter<AI, BI>(&mut self, ai: &mut AI, bi: &mut BI) -> Option<(A, B)>
where AI: Iterator<Item=A>, BI: Iterator<Item=B>
{
Some(match take(self) {
Remainder::Nothing => {
let a = ai.next()?;
let b = bi.next()?;
(a, b)
}
Remainder::SomeA(a) => {
let b = bi.next()?;
(a, b)
}
Remainder::SomeB(b) => {
let a = ai.next()?;
(a, b)
}
})
}
}
#[derive(Clone, Debug)]
pub struct RleZip<A, B>
where A: Iterator, B: Iterator,
A::Item: SplitableSpan + HasLength, B::Item: SplitableSpan + HasLength,
{
rem: Remainder<A::Item, B::Item>,
a: A,
b: B,
}
impl<A, B> Iterator for RleZip<A, B>
where A: Iterator, B: Iterator,
A::Item: SplitableSpan + HasLength, B::Item: SplitableSpan + HasLength
{
type Item = (A::Item, B::Item);
fn next(&mut self) -> Option<Self::Item> {
let (mut a, mut b) = self.rem.take_from_iter(&mut self.a, &mut self.b)?;
let a_len = a.len();
let b_len = b.len();
self.rem = match a_len.cmp(&b_len) {
Ordering::Equal => {
Remainder::Nothing
}
Ordering::Less => {
let b_rem = b.truncate(a_len);
Remainder::SomeB(b_rem)
}
Ordering::Greater => {
let a_rem = a.truncate(b_len);
Remainder::SomeA(a_rem)
}
};
Some((a, b))
}
}
pub fn rle_zip<A, B>(a: A, b: B) -> RleZip<A, B>
where A: Iterator, B: Iterator,
A::Item: SplitableSpan + HasLength, B::Item: SplitableSpan + HasLength
{
RleZip {
rem: Remainder::Nothing,
a,
b
}
}
pub fn rle_zip3<A, B, C>(a: A, b: B, c: C) -> impl Iterator<Item=(A::Item, B::Item, C::Item)>
where A: Iterator, B: Iterator, C: Iterator,
A::Item: SplitableSpan + HasLength,
B::Item: SplitableSpan + HasLength,
C::Item: SplitableSpan + HasLength,
{
rle_zip(rle_zip(a, b), c).map(|((a, b), c)| (a, b, c))
}
#[cfg(test)]
mod test {
use super::*;
use crate::vendor::rle::RleRun;
fn check_zip(a: &[RleRun<u32>], b: &[RleRun<u32>], expect: &[(RleRun<u32>, RleRun<u32>)]) {
assert_eq!(rle_zip(a.iter().copied(), b.iter().copied())
.collect::<Vec<_>>(), expect);
assert_eq!(rle_zip(b.iter().copied(), a.iter().copied())
.map(|(a, b)| (b, a))
.collect::<Vec<_>>(), expect);
}
#[test]
fn smoke() {
let one = vec![
RleRun { val: 1, len: 1 },
RleRun { val: 2, len: 4 }
];
let two = vec![
RleRun { val: 11, len: 4 },
RleRun { val: 12, len: 1 }
];
let expected = vec![
(RleRun { val: 1, len: 1 }, RleRun { val: 11, len: 1}),
(RleRun { val: 2, len: 3 }, RleRun { val: 11, len: 3}),
(RleRun { val: 2, len: 1 }, RleRun { val: 12, len: 1}),
];
check_zip(&one, &two, &expected);
}
#[test]
fn one_is_longer() {
let one = vec![
RleRun { val: 1, len: 100 },
];
let two = vec![
RleRun { val: 11, len: 10 },
];
let expected = vec![
(RleRun { val: 1, len: 10 }, RleRun { val: 11, len: 10}),
];
check_zip(&one, &two, &expected);
}
}