use crate::*;
#[cfg(feature = "alloc")]
#[test]
fn take_short_circuit() {
use alloc::vec;
use alloc::vec::Vec;
struct Iter<'a> {
exhausted: &'a mut bool,
}
impl<'a> InternalIterator for Iter<'a> {
type Item = i32;
fn try_for_each<T, F>(self, mut f: F) -> ControlFlow<T>
where
F: FnMut(i32) -> ControlFlow<T>,
{
for &x in &[1, 2, 3] {
f(x)?;
}
*self.exhausted = true;
ControlFlow::Continue(())
}
}
let mut exhausted = false;
let iter = Iter {
exhausted: &mut exhausted,
};
let items = iter.take(3).collect::<Vec<_>>();
assert_eq!(items, vec![1, 2, 3]);
assert!(!exhausted);
}
#[test]
fn take_empty() {
struct Iter;
impl InternalIterator for Iter {
type Item = i32;
fn try_for_each<T, F>(self, _: F) -> ControlFlow<T>
where
F: FnMut(i32) -> ControlFlow<T>,
{
unreachable!()
}
}
assert_eq!(Iter.take(0).next(), None);
}
#[test]
fn map_side_effects_preserved() {
let mut closure_calls = 0;
let count = (10..25)
.into_internal()
.map(|x| {
closure_calls += 1;
x * 2
})
.count();
assert_eq!(count, 15);
assert_eq!(closure_calls, 15);
let mut closure_calls = 0;
let nth = (10..25)
.into_internal()
.map(|x| {
closure_calls += 1;
x * 2
})
.nth(12);
assert_eq!(nth, Some(44));
assert_eq!(closure_calls, 13);
let mut closure_calls = 0;
let last = (10..25)
.into_internal()
.map(|x| {
closure_calls += 1;
x * 2
})
.last();
assert_eq!(last, Some(48));
assert_eq!(closure_calls, 15);
}
#[test]
fn clone_side_effects_preserved() {
use core::cell::Cell;
struct Weird<'a>(i32, &'a Cell<i32>);
impl Clone for Weird<'_> {
fn clone(&self) -> Self {
self.1.set(self.1.get() + 1);
Weird(self.0, self.1)
}
}
let clones = Cell::new(0);
let weirds = [
&Weird(0, &clones),
&Weird(1, &clones),
&Weird(2, &clones),
&Weird(3, &clones),
];
let count = weirds
.into_internal_iter()
.cloned()
.count();
assert_eq!(count, 4);
assert_eq!(clones.get(), 4);
clones.set(0);
let nth = weirds
.into_internal_iter()
.cloned()
.nth(2);
assert_eq!(nth.unwrap().0, 2);
assert_eq!(clones.get(), 3);
clones.set(0);
let last = weirds
.into_internal_iter()
.cloned()
.last();
assert_eq!(last.unwrap().0, 3);
assert_eq!(clones.get(), 4);
}
#[cfg(feature = "alloc")]
#[test]
fn readme_example() {
use alloc::vec;
use alloc::vec::Vec;
#[derive(Clone)]
struct Tree(i32, Vec<Tree>);
impl Tree {
fn into_iter(self) -> TreeIter {
TreeIter {
tree: self,
position: vec![0],
}
}
fn into_internal_iter(self) -> TreeInternalIter {
TreeInternalIter {
tree: self,
}
}
}
struct TreeIter {
tree: Tree,
position: Vec<usize>,
}
fn find_subtree<'a>(tree: &'a Tree, pos: &[usize]) -> Option<&'a Tree> {
match pos {
[] => Some(tree),
[idx, rest @ ..] => {
let child = &tree.1.get(*idx)?;
find_subtree(child, rest)
}
}
}
impl Iterator for TreeIter {
type Item = i32;
fn next(&mut self) -> Option<i32> {
loop {
match self.position.as_slice() {
[0, rest @ ..] => {
let current_tree = find_subtree(&self.tree, &rest);
if let Some(tree) = current_tree {
let result = Some(tree.0);
if !tree.1.is_empty() {
self.position.push(0);
} else {
*self.position.last_mut().unwrap() += 1;
}
return result;
} else {
self.position.pop();
*self.position.last_mut().unwrap() += 1;
}
}
[1] => {
return None;
}
_ => unreachable!(),
}
}
}
}
struct TreeInternalIter {
tree: Tree,
}
fn for_each_helper<T>(
tree: Tree,
f: &mut impl FnMut(i32) -> ControlFlow<T>,
) -> ControlFlow<T> {
f(tree.0)?;
for child in tree.1 {
for_each_helper(child, f)?
}
ControlFlow::Continue(())
}
impl InternalIterator for TreeInternalIter {
type Item = i32;
fn try_for_each<T, F>(self, mut f: F) -> ControlFlow<T>
where
F: FnMut(i32) -> ControlFlow<T>,
{
for_each_helper(self.tree, &mut f)
}
}
let tree = Tree(4, vec![
Tree(1, vec![]),
Tree(3, vec![
Tree(5, vec![]),
]),
Tree(2, vec![]),
]);
let iterator_result = tree
.clone()
.into_iter()
.map(|x| x * 2)
.filter(|&x| x > 5)
.flat_map(|x| [x, x * 10])
.collect::<Vec<_>>();
assert_eq!(iterator_result, vec![8, 80, 6, 60, 10, 100]);
let internal_iterator_result = tree
.clone()
.into_internal_iter()
.map(|x| x * 2)
.filter(|&x| x > 5)
.flat_map(|x| [x, x * 10])
.collect::<Vec<_>>();
assert_eq!(internal_iterator_result, vec![8, 80, 6, 60, 10, 100]);
}