use crate::error::Result;
pub struct StoredIterator<T> {
items: std::vec::IntoIter<T>,
total: usize,
consumed: usize,
}
impl<T> StoredIterator<T> {
pub(crate) fn from_vec(items: Vec<T>) -> Self {
let total = items.len();
StoredIterator { items: items.into_iter(), total, consumed: 0 }
}
pub fn total(&self) -> usize {
self.total
}
pub fn consumed(&self) -> usize {
self.consumed
}
pub fn remaining(&self) -> usize {
self.total.saturating_sub(self.consumed)
}
pub fn is_exhausted(&self) -> bool {
self.remaining() == 0
}
}
impl<T> Iterator for StoredIterator<T> {
type Item = Result<T>;
fn next(&mut self) -> Option<Self::Item> {
match self.items.next() {
Some(item) => {
self.consumed += 1;
Some(Ok(item))
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.remaining();
(remaining, Some(remaining))
}
}
impl<T> ExactSizeIterator for StoredIterator<T> {
fn len(&self) -> usize {
self.remaining()
}
}
impl<T> std::iter::FusedIterator for StoredIterator<T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_iterator_is_exhausted() {
let mut iter: StoredIterator<i32> = StoredIterator::from_vec(vec![]);
assert_eq!(iter.total(), 0);
assert_eq!(iter.remaining(), 0);
assert!(iter.is_exhausted());
assert!(iter.next().is_none());
}
#[test]
fn iterator_yields_in_order_and_tracks_progress() {
let mut iter = StoredIterator::from_vec(vec![1, 2, 3]);
assert_eq!(iter.total(), 3);
assert_eq!(iter.size_hint(), (3, Some(3)));
assert_eq!(iter.next().unwrap().unwrap(), 1);
assert_eq!(iter.consumed(), 1);
assert_eq!(iter.remaining(), 2);
assert_eq!(iter.next().unwrap().unwrap(), 2);
assert_eq!(iter.next().unwrap().unwrap(), 3);
assert!(iter.next().is_none());
assert!(iter.is_exhausted());
}
#[test]
fn iterator_is_fused() {
let mut iter = StoredIterator::from_vec(vec![10]);
assert_eq!(iter.next().unwrap().unwrap(), 10);
assert!(iter.next().is_none());
assert!(iter.next().is_none());
assert!(iter.next().is_none());
}
#[test]
fn exact_size_iterator() {
let iter = StoredIterator::from_vec(vec!["a", "b", "c"]);
assert_eq!(iter.len(), 3);
}
}