A performant iterator providing double peek functionality.
This crate provides a [`Peekable`](https://docs.rs/peek_again/latest/peek_again/struct.Peekable.html)
iterator adapter that allows looking ahead by up to two elements without advancing the
iterator. It maintains performance parity with [`core::iter::Peekable`](https://doc.rust-lang.org/core/iter/struct.Peekable.html)
for most single peek operations as well as `next` invocations.
# Key Features
- **Double Peek**: Look ahead by up to two elements while maintaining iterator position.
- **Performance**: Most single peek operations are as fast as `core::iter::Peekable`.
- **Greater Control**: Enhanced functionality for conditional iteration and element consumption.
# Basic Usage
```rust
use peek_again::Peekable;
let mut iter = Peekable::new([1, 2, 3].into_iter());
assert_eq!(iter.peek(), Some(&1)); // Look at next element
assert_eq!(iter.peek_2(), Some(&2)); // Look two elements ahead
assert_eq!(iter.next(), Some(1)); // Iterator position unchanged
```
# Enhanced Peek Control
The [`Peek`](https://docs.rs/peek_again/latest/peek_again/struct.Peek.html) type returned by
[`peek`](https://docs.rs/peek_again/latest/peek_again/struct.Peekable.html#method.peek) provides
additional control over iteration:
```rust
use peek_again::Peekable;
let mut iter = Peekable::new([1, 2, 3].into_iter());
let mut peek = iter.peek();
// Examine current and next elements
assert_eq!(peek, Some(&1));
assert_eq!(peek.peek(), Some(&2));
// Conditionally consume elements (moving the iterator forward)
if peek == Some(&1) {
assert_eq!(peek.consume(), Some(1));
}
```
# Conditional Draining
The [`drain_if`](https://docs.rs/peek_again/latest/peek_again/struct.Peek.html#method.drain_if) method
allows consuming multiple elements based on lookahead:
```rust
use peek_again::Peekable;
let mut iter = Peekable::new([1, 2, 3].into_iter());
let peek = iter.peek();
peek.drain_if(|&next| next == 2)
.map_or_else(
|_peek| unreachable!("The second element is two."),
|(curr, next)| {
assert_eq!(curr, Some(1));
assert_eq!(next, 2);
}
);
```
# Safety
This crate is marked with `#![forbid(unsafe_code)]` and employs design by contract
principles, making the property tests far more meaningful. These contracts are also
checked via `kani`.
This crate does have an `allow-unsafe` feature flag, this is not enabled by default,
when enabled this crate will use `core::hint::unreachable_unchecked` for states
that are guaranteed to be unreachable, offering a 15% performance improvement for
certain operations.