Expand description
This crate provides a ShadowCountedIter which counts every iteration to a hidden
counter. It is possible to create nested iterators which can commit their counter to their parent
iterator. Additionally, iterators can carry supplemental data through the iteration process.
Unlike the std std::iter::Enumerate iterator, the ShadowCountedIter does not return the counter
to the user, instead it has to be queried with the ShadowCountedIter::counter() method.
We also provide a IntoShadowCounted extension trait which converts any iterator into a
ShadowCountedIter.
§Features
- Basic counting: Track iteration progress without returning indices
- Nested iteration: Create child iterators that inherit parent state
- Commit mechanism: Propagate counts from nested iterators to parents
- Supplemental data: Carry arbitrary data through iteration with optional commit logic
§Examples
§Basic Counting
use shadow_counted::{ShadowCountedIter, IntoShadowCounted};
let vec = vec![1, 2, 3];
let mut iter = vec.into_iter().shadow_counted();
while let Some(_) = iter.next() {}
assert_eq!(iter.counter(), 3);§Nested Counting
use shadow_counted::{ShadowCountedIter, IntoShadowCounted};
// Make a datastructure that may hold nested elements.
#[derive(Debug, PartialEq)]
enum Nodes<'a, T> {
Leaf(T),
Nested(&'a [Nodes<'a, T>]),
}
let items = &[
Nodes::Leaf(1),
Nodes::Nested(&[Nodes::Leaf(2), Nodes::Leaf(3)]),
Nodes::Leaf(4),
];
// iterate over the outer
let mut sc_iter = items.into_iter().shadow_counted();
assert_eq!(sc_iter.next(), Some(&Nodes::Leaf(1)));
// the 2nd element is `Node::Nested(..)'
let element = sc_iter.next().unwrap();
// since we dont want to count `Nested` we substract one from the counter
sc_iter.add(-1);
let Nodes::Nested(nested) = element else {unreachable!()};
let mut nested_iter = nested.into_iter().nested_shadow_counted(&mut sc_iter);
assert_eq!(nested_iter.next(), Some(&Nodes::Leaf(2)));
assert_eq!(nested_iter.next(), Some(&Nodes::Leaf(3)));
// reaching the end, commit to the parent iter
assert_eq!(nested_iter.next(), None);
// eventually a nested iter must be committed when its progress should be counted
nested_iter.commit();
// back to the outer
assert_eq!(sc_iter.counter(), 3);
assert_eq!(sc_iter.next(), Some(&Nodes::Leaf(4)));
assert_eq!(sc_iter.counter(), 4);§Supplemental Data
You can attach supplemental data to iterators that gets cloned when nesting and can be
committed back to the parent. The parent data must use interior mutability (like Cell)
to allow updates during commit:
use shadow_counted::{Commit, ShadowCountedIter, IntoShadowCounted};
use std::cell::Cell;
#[derive(Clone, Default, Debug)]
struct Stats {
count: Cell<u32>,
}
impl Commit for Stats {
fn commit(&self, from: Self) {
self.count.set(self.count.get() + from.count.get());
}
}
let mut parent = ShadowCountedIter::new_with(
vec![1, 2].into_iter(),
Stats::default()
);
let mut nested = vec![3, 4].into_iter().nested_shadow_counted(&mut parent);
nested.supplement_mut().count.set(5);
nested.commit().unwrap();
// Stats were committed from nested to parent
assert_eq!(parent.supplement().count.get(), 5);§Development
shadow_counted is distributed via radicle its identifier is rad:zuUvsqfRdsC1NraTegYHBMtCmm2Z
You can clone the repository using git by:
git clone https://seed.pipapo.org/zuUvsqfRdsC1NraTegYHBMtCmm2Z.git shadow_counted
When you spot a problem or need a new feature feel free to open an issue or (prefered!) send a PR.
Commits and other git operations are augmented and validated with
bar. For
contributors it is recommened to enable bar too by calling ./bar activate
within a checked out unsynn repository.
§Contribution/Coding Guidelines
Chances to get contributions merged increase when you:
- Include documentation following the existing documentation practice. Write examples/doctests.
- Passing
./bar lintsis a absolute requirement, I am not even looking at contributions that fail basic lint and formatting checks. Hint: try./bar dwimto apply formatting and trivial fixes. - Ideally passing
./barwithout errors or warnings. Although if some problems and errors remain to be discussed then a WIP-PR failing tests is temporary acceptable. - Passing test-coverage with
./bar cargo_mutants. - When you activated the githooks with ‘./bar activate’ then the policies for viable commits are enforced automatically.
- Implement reasonable complete things. Not everything needs to be included in a first version, but it must be usable.
Structs§
- Shadow
Counted Iter - An iterator that counts every iteration and optionally commits the count to a parent iterator. Can carry supplemental data of type S through the iteration process.
Traits§
- Commit
- Trait for types that can be committed from a child to a parent during nesting.
- Into
Shadow Counted - A extension trait to convert any iterator into a ShadowCountedIter.
This must be in scope to use the
shadow_countedmethod on an iterator. When possible theFromandIntomay be more convenient to use.