#[derive(Debug, PartialEq)]
pub struct Partial {
pub size: u16,
pub new: bool,
}
pub struct IncrementalIterator<I: Iterator<Item = usize>> {
iter: I,
partial: usize,
}
impl<I: Iterator<Item = usize>> IncrementalIterator<I> {
#[inline]
pub fn new<J: IntoIterator<IntoIter = I>>(iter: J) -> Self {
Self {
iter: iter.into_iter(),
partial: 0,
}
}
#[inline]
pub fn is_incomplete(&self) -> bool {
self.partial > 0
}
#[inline]
pub fn next_partial(&mut self, limit: u16) -> Option<Partial> {
if self.partial > 0 {
Some(Partial {
new: false,
size: if self.partial > limit.into() {
self.partial = unsafe { self.partial.unchecked_sub(limit as usize) };
limit
} else {
let ret = self.partial as u16;
self.partial = 0;
ret
},
})
} else {
match self.iter.next() {
Some(new) => Some(Partial {
new: true,
size: if new > limit.into() {
self.partial = unsafe { new.unchecked_sub(limit as usize) };
limit
} else {
new as u16
},
}),
None => None,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
struct PartialTester<I: Iterator<Item = usize>> {
partial: IncrementalIterator<I>,
}
impl<I: Iterator<Item = usize>> PartialTester<I> {
fn assert(&mut self, limit: u16, size: u16, new: bool) {
assert_eq!(
self.partial.next_partial(limit),
Some(Partial { size, new })
);
}
}
#[test]
fn test_partial_iterator() {
let mut ap = PartialTester {
partial: IncrementalIterator::new([1, 7, 3, 2, 5]),
};
ap.assert(2, 1, true);
ap.assert(5, 5, true);
assert!(ap.partial.is_incomplete());
ap.assert(1, 1, false);
assert!(ap.partial.is_incomplete());
ap.assert(1, 1, false);
ap.assert(3, 3, true);
ap.assert(1, 1, true);
assert!(ap.partial.is_incomplete());
ap.assert(8, 1, false);
ap.assert(4, 4, true);
ap.assert(0, 0, false);
ap.assert(1, 1, false);
assert!(ap.partial.next_partial(0).is_none());
}
}