#![doc = include_str!("../README.md")]
use std::cell::Cell;
pub trait Commit {
fn commit(&self, from: Self);
}
impl Commit for () {
fn commit(&self, _from: Self) {}
}
impl<T> Commit for std::rc::Rc<T> {
fn commit(&self, _from: Self) {}
}
impl<T> Commit for std::sync::Arc<T> {
fn commit(&self, _from: Self) {}
}
#[derive(Debug, Clone)]
pub struct ShadowCountedIter<'a, I: Iterator, S = ()> {
iter: I,
counter: ShadowCounter<'a, S>,
}
impl<'a, I: Iterator, S: Default> ShadowCountedIter<'a, I, S> {
pub fn new(iter: I) -> Self {
Self {
iter,
counter: ShadowCounter::new(),
}
}
}
impl<'a, I: Iterator, S> ShadowCountedIter<'a, I, S> {
pub fn new_with(iter: I, supplement: S) -> Self {
Self {
iter,
counter: ShadowCounter::new_with_data(supplement),
}
}
pub fn supplement(&self) -> &S {
&self.counter.data
}
pub fn supplement_mut(&mut self) -> &mut S {
&mut self.counter.data
}
}
impl<'a, I: Iterator, S: Clone> ShadowCountedIter<'a, I, S> {
pub fn new_nested<'b, T: Iterator>(
iter: I,
parent: &'a mut ShadowCountedIter<'b, T, S>,
) -> Self {
Self {
iter,
counter: parent.counter.nest(),
}
}
}
impl<'a, I: Iterator, S> ShadowCountedIter<'a, I, S> {
pub fn new_nested_with<'b, T: Iterator>(
iter: I,
parent: &'a mut ShadowCountedIter<'b, T, S>,
supplement: S,
) -> Self
where
S: Clone,
{
Self {
iter,
counter: parent.counter.nest_with(supplement),
}
}
}
impl<'a, I: Iterator, S: Commit> ShadowCountedIter<'a, I, S> {
pub fn commit(self) -> Result<(), Self> {
let Self { iter, counter } = self;
counter.commit().map_err(|counter| Self { iter, counter })
}
pub fn into_inner_iter(self) -> I {
self.iter
}
}
impl<I: Iterator, S> ShadowCountedIter<'_, I, S> {
#[inline]
pub fn add(&mut self, delta: isize) {
self.counter.add(delta)
}
#[inline]
pub fn counter(&self) -> usize {
self.counter.get()
}
}
impl<I: Iterator, S> Iterator for ShadowCountedIter<'_, I, S> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
Some(item) => {
*self.counter.counter.get_mut() += 1;
Some(item)
}
None => None,
}
}
}
impl<I: Iterator, S> AsRef<I> for ShadowCountedIter<'_, I, S> {
fn as_ref(&self) -> &I {
&self.iter
}
}
impl<I: Iterator + ExactSizeIterator, S> ExactSizeIterator for ShadowCountedIter<'_, I, S> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<I: Iterator + std::iter::FusedIterator, S> std::iter::FusedIterator
for ShadowCountedIter<'_, I, S>
{
}
impl<I: DoubleEndedIterator, S> DoubleEndedIterator for ShadowCountedIter<'_, I, S> {
fn next_back(&mut self) -> Option<Self::Item> {
match self.iter.next_back() {
Some(item) => {
*self.counter.counter.get_mut() += 1;
Some(item)
}
None => None,
}
}
}
pub trait IntoShadowCounted {
fn shadow_counted<'a>(self) -> ShadowCountedIter<'a, Self, ()>
where
Self: Sized + Iterator,
{
ShadowCountedIter::new(self)
}
fn nested_shadow_counted<'a, I: Iterator, S: Clone>(
self,
parent: &'a mut ShadowCountedIter<'_, I, S>,
) -> ShadowCountedIter<'a, Self, S>
where
Self: Sized + Iterator,
{
ShadowCountedIter::new_nested(self, parent)
}
}
impl<T: Iterator> IntoShadowCounted for T {}
impl<T: Iterator> From<T> for ShadowCountedIter<'_, T, ()> {
fn from(iter: T) -> Self {
ShadowCountedIter::new(iter)
}
}
#[derive(Debug, Clone)]
struct ShadowCounter<'a, S = ()> {
counter: Cell<usize>,
created_at: usize,
parent: Option<&'a ShadowCounter<'a, S>>,
data: S,
}
impl<'a, S: Clone> ShadowCounter<'a, S> {
fn nest(&'a self) -> Self {
Self {
counter: self.counter.clone(),
created_at: self.counter.get(),
parent: Some(self),
data: self.data.clone(),
}
}
fn nest_with(&'a self, data: S) -> Self {
Self {
counter: self.counter.clone(),
created_at: self.counter.get(),
parent: Some(self),
data,
}
}
}
impl<S: Default> ShadowCounter<'_, S> {
fn new() -> Self {
Self {
counter: 0.into(),
created_at: 0,
parent: None,
data: S::default(),
}
}
}
impl<S> ShadowCounter<'_, S> {
fn new_with_data(data: S) -> Self {
Self {
counter: 0.into(),
created_at: 0,
parent: None,
data,
}
}
#[inline]
fn get(&self) -> usize {
self.counter.get()
}
#[inline]
fn add(&mut self, delta: isize) {
self.counter
.set(self.counter.get().wrapping_add(delta as usize));
}
}
impl<S: Commit> ShadowCounter<'_, S> {
fn commit(self) -> Result<(), Self> {
if let Some(p) = self.parent {
if p.counter.get() == self.created_at {
p.counter.set(self.counter.get());
p.data.commit(self.data);
return Ok(());
}
}
Err(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty() {
let vec: Vec<i32> = vec![];
let mut iter: ShadowCountedIter<'_, _, ()> = ShadowCountedIter::new(vec.into_iter());
while iter.next().is_some() {}
assert_eq!(iter.counter(), 0);
}
#[test]
fn commit_nonnested() {
let vec: Vec<i32> = vec![];
let mut iter: ShadowCountedIter<'_, _, ()> = ShadowCountedIter::new(vec.into_iter());
while iter.next().is_some() {}
assert!(iter.commit().is_err());
}
#[test]
fn test_basic_counting() {
let vec = vec![1, 2, 3];
let mut iter: ShadowCountedIter<'_, _, ()> = ShadowCountedIter::new(vec.into_iter());
while iter.next().is_some() {}
assert_eq!(iter.counter(), 3);
}
#[test]
fn test_empty_iterator() {
let vec: Vec<i32> = vec![];
let mut iter: ShadowCountedIter<'_, _, ()> = ShadowCountedIter::new(vec.into_iter());
while iter.next().is_some() {}
assert_eq!(iter.counter(), 0);
}
#[test]
fn test_commit() {
let mut parent_iter = vec![1, 2, 3].into_iter().shadow_counted();
parent_iter.next();
let mut nested_iter = vec![4, 5]
.into_iter()
.nested_shadow_counted(&mut parent_iter);
nested_iter.next();
nested_iter.commit().unwrap();
assert_eq!(parent_iter.counter(), 2);
}
#[test]
fn test_commit_twice() {
let mut parent_iter = vec![1, 2, 3].into_iter().shadow_counted();
parent_iter.next();
let mut nested_iter = vec![4, 5]
.into_iter()
.nested_shadow_counted(&mut parent_iter);
let nested_iter2 = nested_iter.clone();
nested_iter.next();
nested_iter.commit().unwrap();
assert!(nested_iter2.commit().is_err());
assert_eq!(parent_iter.counter(), 2);
}
#[test]
fn test_two_commits() {
let mut parent_iter = vec![1, 2, 3].into_iter().shadow_counted();
parent_iter.next();
let mut nested_iter = vec![4].into_iter().nested_shadow_counted(&mut parent_iter);
nested_iter.next();
nested_iter.commit().unwrap();
parent_iter.next();
let mut nested_iter = vec![5].into_iter().nested_shadow_counted(&mut parent_iter);
nested_iter.next();
nested_iter.commit().unwrap();
parent_iter.next();
assert_eq!(parent_iter.counter(), 5);
}
#[test]
fn test_shadow_count_iter() {
#[derive(Debug, PartialEq)]
enum Nodes<'a, T> {
Leaf(T),
Nested(&'a [Nodes<'a, T>]),
}
let items = &[
Nodes::Leaf(1),
Nodes::Leaf(2),
Nodes::Nested(&[Nodes::Leaf(3), Nodes::Leaf(4), Nodes::Leaf(5)]),
Nodes::Leaf(6),
];
let mut sc_iter = items.iter().shadow_counted();
assert!((sc_iter.counter()) == (0));
assert!((sc_iter.next()) == (Some(&Nodes::Leaf(1))));
assert!((sc_iter.counter()) == (1));
assert!((sc_iter.next()) == (Some(&Nodes::Leaf(2))));
assert!((sc_iter.counter()) == (2));
let nested = sc_iter.next().unwrap();
assert!((sc_iter.counter()) == (3));
assert!((nested) == (&Nodes::Nested(&[Nodes::Leaf(3), Nodes::Leaf(4), Nodes::Leaf(5)])));
let Nodes::Nested(nested) = nested else {
panic!()
};
let mut nested_iter = nested.iter().nested_shadow_counted(&mut sc_iter);
assert_eq!(nested_iter.counter(), 3);
assert_eq!(nested_iter.next(), Some(&Nodes::Leaf(3)));
assert_eq!(nested_iter.counter(), 4);
assert_eq!(nested_iter.next(), Some(&Nodes::Leaf(4)));
assert_eq!(nested_iter.counter(), 5);
assert_eq!(nested_iter.next(), Some(&Nodes::Leaf(5)));
assert_eq!(nested_iter.counter(), 6);
assert_eq!(nested_iter.next(), None);
assert_eq!(nested_iter.counter(), 6);
nested_iter.commit().unwrap();
assert_eq!(sc_iter.counter(), 6);
assert_eq!(sc_iter.next(), Some(&Nodes::Leaf(6)));
assert_eq!(sc_iter.counter(), 7);
}
#[test]
fn test_supplement_with_custom_data() {
#[derive(Debug, Clone, Default, PartialEq)]
struct MyData {
value: u32,
}
impl Commit for MyData {
fn commit(&self, _from: Self) {}
}
let vec = vec![1, 2, 3];
let data = MyData { value: 42 };
let mut iter = ShadowCountedIter::new_with(vec.into_iter(), data);
assert_eq!(iter.supplement().value, 42);
while iter.next().is_some() {}
assert_eq!(iter.counter(), 3);
assert_eq!(iter.supplement().value, 42);
}
#[test]
fn test_supplement_mut() {
#[derive(Debug, Clone, Default, PartialEq)]
struct MyData {
value: u32,
}
impl Commit for MyData {
fn commit(&self, _from: Self) {}
}
let mut iter = ShadowCountedIter::new_with(vec![1, 2].into_iter(), MyData { value: 10 });
assert_eq!(iter.supplement().value, 10);
iter.supplement_mut().value = 20;
assert_eq!(iter.supplement().value, 20);
}
#[test]
fn test_nested_data_cloned() {
#[derive(Debug, Clone, Default, PartialEq)]
struct MyData {
value: u32,
}
impl Commit for MyData {
fn commit(&self, _from: Self) {}
}
let mut parent = ShadowCountedIter::new_with(vec![1].into_iter(), MyData { value: 42 });
let nested = vec![2].into_iter().nested_shadow_counted(&mut parent);
assert_eq!(nested.supplement().value, 42); }
#[test]
fn test_data_committed() {
use std::cell::Cell;
#[derive(Debug, Clone, Default)]
struct Counter {
count: Cell<u32>,
}
impl Commit for Counter {
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(), Counter::default());
parent.next();
let mut nested = vec![3, 4].into_iter().nested_shadow_counted(&mut parent);
nested.supplement_mut().count.set(5);
nested.next();
nested.next();
nested.commit().unwrap();
assert_eq!(parent.supplement().count.get(), 5); }
}