rust/library/core/tests/iter/adapters/mod.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

210 lines
4.2 KiB
Rust
Raw Normal View History

2022-01-02 10:31:56 -06:00
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 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
}
}
2022-01-02 10:31:56 -06:00
#[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);
}
}