Slide 20
Slide 20 text
Powerful Primitives: The Abstraction
pub fn zip<'a>(&'a self, other: &'a Subset) -> ZipIter<'a> {
ZipIter {
a_segs: self.segments.as_slice(),
b_segs: other.segments.as_slice(),
a_i: 0,
b_i: 0,
a_consumed: 0,
b_consumed: 0,
consumed: 0,
}
}
/// See `Subset::zip`
pub struct ZipIter<'a> {
a_segs: &'a [Segment],
b_segs: &'a [Segment],
a_i: usize,
b_i: usize,
a_consumed: usize,
b_consumed: usize,
pub consumed: usize,
}
/// See `Subset::zip`
#[derive(Clone, Debug)]
pub struct ZipSegment {
len: usize,
a_count: usize,
b_count: usize,
}
impl<'a> Iterator for ZipIter<'a> {
type Item = ZipSegment;
/// Consume as far as possible from `self.consumed` until reaching a
/// segment boundary in either `Subset`, and return the resulting
/// `ZipSegment`. Will panic if it reaches the end of one `Subset` before
/// the other, that is when they have different total length.
fn next(&mut self) -> Option {
match (self.a_segs.get(self.a_i), self.b_segs.get(self.b_i)) {
(None, None) => None,
(None, Some(_)) | (Some(_), None) => panic!("can't zip Subsets of different base lengths."),
(Some(&Segment {len: a_len, count: a_count}), Some(&Segment {len: b_len, count: b_count})) => {
let len = if a_len + self.a_consumed == b_len + self.b_consumed {
self.a_consumed += a_len; self.a_i += 1;
self.b_consumed += b_len; self.b_i += 1;
self.a_consumed - self.consumed
} else if a_len + self.a_consumed < b_len + self.b_consumed {
self.a_consumed += a_len; self.a_i += 1;
self.a_consumed - self.consumed
} else {
self.b_consumed += b_len; self.b_i += 1;
self.b_consumed - self.consumed
};
self.consumed += len;
Some(ZipSegment {len, a_count, b_count})
}
}
}
}