rust/library/core/tests/iter/adapters/mod.rs
Frank King 97c953f561 Add Iterator::map_windows
This is inherited from the old PR.

This method returns an iterator over mapped windows of the starting
iterator. Adding the more straight-forward `Iterator::windows` is not
easily possible right now as the items are stored in the iterator type,
meaning the `next` call would return references to `self`. This is not
allowed by the current `Iterator` trait design. This might change once
GATs have landed.

The idea has been brought up by @m-ou-se here:
https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Iterator.3A.3A.7Bpairwise.2C.20windows.7D/near/224587771

Co-authored-by: Lukas Kalbertodt <lukas.kalbertodt@gmail.com>
2023-08-11 07:26:51 +08:00

211 lines
4.2 KiB
Rust

mod array_chunks;
mod by_ref_sized;
mod chain;
mod cloned;
mod copied;
mod cycle;
mod enumerate;
mod filter;
mod filter_map;
mod flat_map;
mod flatten;
mod fuse;
mod inspect;
mod intersperse;
mod map;
mod map_windows;
mod peekable;
mod scan;
mod skip;
mod skip_while;
mod step_by;
mod take;
mod take_while;
mod zip;
use core::cell::Cell;
/// An iterator that panics whenever `next` or `next_back` is called
/// after `None` has already been returned. This does not violate
/// `Iterator`'s contract. Used to test that iterator adapters don't
/// poll their inner iterators after exhausting them.
pub struct NonFused<I> {
iter: I,
done: bool,
}
impl<I> NonFused<I> {
pub fn new(iter: I) -> Self {
Self { iter, done: false }
}
}
impl<I> Iterator for NonFused<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
assert!(!self.done, "this iterator has already returned None");
self.iter.next().or_else(|| {
self.done = true;
None
})
}
}
impl<I> DoubleEndedIterator for NonFused<I>
where
I: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
assert!(!self.done, "this iterator has already returned None");
self.iter.next_back().or_else(|| {
self.done = true;
None
})
}
}
/// An iterator wrapper that panics whenever `next` or `next_back` is called
/// after `None` has been returned.
pub struct Unfuse<I> {
iter: I,
exhausted: bool,
}
impl<I> Unfuse<I> {
pub fn new<T>(iter: T) -> Self
where
T: IntoIterator<IntoIter = I>,
{
Self { iter: iter.into_iter(), exhausted: false }
}
}
impl<I> Iterator for Unfuse<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
assert!(!self.exhausted);
let next = self.iter.next();
self.exhausted = next.is_none();
next
}
}
impl<I> DoubleEndedIterator for Unfuse<I>
where
I: DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
assert!(!self.exhausted);
let next = self.iter.next_back();
self.exhausted = next.is_none();
next
}
}
pub struct Toggle {
is_empty: bool,
}
impl Iterator for Toggle {
type Item = ();
// alternates between `None` and `Some(())`
fn next(&mut self) -> Option<Self::Item> {
if self.is_empty {
self.is_empty = false;
None
} else {
self.is_empty = true;
Some(())
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.is_empty { (0, Some(0)) } else { (1, Some(1)) }
}
}
impl DoubleEndedIterator for Toggle {
fn next_back(&mut self) -> Option<Self::Item> {
self.next()
}
}
/// This is an iterator that follows the Iterator contract,
/// but it is not fused. After having returned None once, it will start
/// producing elements if .next() is called again.
pub struct CycleIter<'a, T> {
index: usize,
data: &'a [T],
}
impl<'a, T> CycleIter<'a, T> {
pub fn new(data: &'a [T]) -> Self {
Self { index: 0, data }
}
}
impl<'a, T> Iterator for CycleIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
let elt = self.data.get(self.index);
self.index += 1;
self.index %= 1 + self.data.len();
elt
}
}
#[derive(Debug)]
struct CountClone(Cell<i32>);
impl CountClone {
pub fn new() -> Self {
Self(Cell::new(0))
}
}
impl PartialEq<i32> for CountClone {
fn eq(&self, rhs: &i32) -> bool {
self.0.get() == *rhs
}
}
impl Clone for CountClone {
fn clone(&self) -> Self {
let ret = CountClone(self.0.clone());
let n = self.0.get();
self.0.set(n + 1);
ret
}
}
#[derive(Debug, Clone)]
struct CountDrop<'a> {
dropped: bool,
count: &'a Cell<usize>,
}
impl<'a> CountDrop<'a> {
pub fn new(count: &'a Cell<usize>) -> Self {
Self { dropped: false, count }
}
}
impl Drop for CountDrop<'_> {
fn drop(&mut self) {
if self.dropped {
panic!("double drop");
}
self.dropped = true;
self.count.set(self.count.get() + 1);
}
}