shadow_counted 0.7.0

An iterator that counts every iteration in a hidden counter, nested iterators may commit the count to parents
Documentation
use shadow_counted::IntoShadowCounted;

/// Test that commit fails on non-nested iterator
#[test]
fn test_commit_fails_on_root() {
    let mut iter = vec![1, 2, 3].into_iter().shadow_counted();
    iter.next();

    let result = iter.commit();
    assert!(result.is_err());
}

/// Test double commit fails
#[test]
fn test_double_commit_fails() {
    let mut parent = vec![1].into_iter().shadow_counted();
    let mut nested = vec![2].into_iter().nested_shadow_counted(&mut parent);

    nested.next();
    assert!(nested.commit().is_ok());

    // Can't use nested anymore after successful commit
}

/// Test commit after clone - only one succeeds
#[test]
fn test_commit_after_clone() {
    let mut parent = vec![1].into_iter().shadow_counted();
    let mut nested = vec![2, 3].into_iter().nested_shadow_counted(&mut parent);

    let nested_clone = nested.clone();

    nested.next();
    nested.next();
    assert!(nested.commit().is_ok());

    // Clone can't commit after original committed
    assert!(nested_clone.commit().is_err());
}

/// Test that commit returns the iterator on error
#[test]
fn test_commit_returns_self_on_error() {
    let mut iter = vec![1, 2, 3].into_iter().shadow_counted();
    iter.next();

    let result = iter.commit();
    assert!(result.is_err());

    // We can recover the iterator
    let recovered = result.unwrap_err();
    assert_eq!(recovered.counter(), 1);
}

/// Test commit propagates count correctly
#[test]
fn test_commit_propagates_count() {
    let mut parent = vec![1].into_iter().shadow_counted();
    assert_eq!(parent.counter(), 0);

    let mut nested = vec![2, 3, 4].into_iter().nested_shadow_counted(&mut parent);
    assert_eq!(nested.counter(), 0);

    for _ in nested.by_ref() {}
    assert_eq!(nested.counter(), 3);

    nested.commit().unwrap();
    assert_eq!(parent.counter(), 3);
}

/// Test commit with add() calls
#[test]
fn test_commit_with_add() {
    let mut parent = vec![1].into_iter().shadow_counted();
    parent.add(10);
    assert_eq!(parent.counter(), 10);

    let mut nested = vec![2].into_iter().nested_shadow_counted(&mut parent);
    assert_eq!(nested.counter(), 10);

    nested.add(5);
    assert_eq!(nested.counter(), 15);

    nested.commit().unwrap();
    assert_eq!(parent.counter(), 15);
}

/// Test that nested created_at matches parent counter
#[test]
fn test_nested_created_at() {
    let mut parent = vec![1, 2, 3].into_iter().shadow_counted();

    parent.next();
    parent.next();
    assert_eq!(parent.counter(), 2);

    let nested = vec![10].into_iter().nested_shadow_counted(&mut parent);
    // Nested should start with parent's counter
    assert_eq!(nested.counter(), 2);
}

/// Test commit with no iterations
#[test]
fn test_commit_zero_iterations() {
    let mut parent = vec![1].into_iter().shadow_counted();
    let nested = vec![2, 3].into_iter().nested_shadow_counted(&mut parent);

    // Commit without consuming
    nested.commit().unwrap();

    assert_eq!(parent.counter(), 0);
}