use std::cmp::Eq;
pub struct RunLength<'a, T> {
items: &'a Vec<T>,
start: usize,
end: usize,
}
impl<'a, T> RunLength<'a, T> {
pub fn new(items: &'a Vec<T>) -> Self {
Self {
items,
start: 0,
end: items.len(),
}
}
}
impl<'a, T> Iterator for RunLength<'a, T>
where
T: Eq,
{
type Item = (&'a T, usize);
fn next(&mut self) -> Option<Self::Item> {
if self.start >= self.end {
return None;
}
let x = &self.items[self.start];
let mut len = 0;
while self.start + len < self.end && &self.items[self.start + len] == x {
len += 1;
}
self.start += len;
Some((x, len))
}
}
impl<'a, T> DoubleEndedIterator for RunLength<'a, T>
where
T: Eq,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.start >= self.end {
return None;
}
let x = &self.items[self.end - 1];
let mut len = 0;
while self.start < self.end - len && &self.items[self.end - len - 1] == x {
len += 1;
}
self.end -= len;
Some((x, len))
}
}
#[cfg(test)]
mod tests {
use super::RunLength;
#[test]
fn test() {
let a = vec![3, 1, 1, 4, 1, 5, 5, 5, 9, 9, 9, 2, 2];
let mut iter = RunLength::new(&a);
assert_eq!(iter.next(), Some((&3, 1)));
assert_eq!(iter.next(), Some((&1, 2)));
assert_eq!(iter.next(), Some((&4, 1)));
assert_eq!(iter.next(), Some((&1, 1)));
assert_eq!(iter.next(), Some((&5, 3)));
assert_eq!(iter.next_back(), Some((&2, 2)));
assert_eq!(iter.next_back(), Some((&9, 3)));
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
}
#[test]
fn test_all() {
let a = vec![7, 7, 7];
let mut iter = RunLength::new(&a);
assert_eq!(iter.next(), Some((&7, 3)));
assert_eq!(iter.next(), None);
}
#[test]
fn empty() {
let a = Vec::<i32>::new();
let mut iter = RunLength::new(&a);
assert_eq!(iter.next(), None);
}
}