use std_::{
cmp::Ordering,
iter::{Product, Sum},
mem,
};
#[derive(Debug, Copy, Clone)]
pub struct LazyOnce<F> {
func: Option<F>,
}
impl<F> LazyOnce<F> {
pub fn new(f: F) -> Self {
LazyOnce { func: Some(f) }
}
}
impl<F, T> Iterator for LazyOnce<F>
where
F: FnOnce() -> T,
{
type Item = T;
fn next(&mut self) -> Option<T> {
self.func.take().map(|f| f())
}
fn size_hint(&self) -> (usize, Option<usize>) {
(1, Some(1))
}
}
impl<F, T> DoubleEndedIterator for LazyOnce<F>
where
F: FnOnce() -> T,
{
fn next_back(&mut self) -> Option<T> {
self.func.take().map(|f| f())
}
}
impl<F, T> ExactSizeIterator for LazyOnce<F> where F: FnOnce() -> T {}
#[derive(Debug, Clone)]
struct Unreplaced<T> {
nth: usize,
current: usize,
with: T,
}
#[derive(Debug, Clone)]
enum ReplaceNthState<T> {
Unreplaced(Unreplaced<T>),
Replaced,
}
#[derive(Debug, Clone)]
pub struct ReplaceNth<I>
where
I: Iterator,
{
iter: I,
state: ReplaceNthState<I::Item>,
}
impl<I> ReplaceNth<I>
where
I: Iterator,
{
pub fn new(iter: I, nth: usize, with: I::Item) -> Self {
Self {
iter,
state: ReplaceNthState::Unreplaced(Unreplaced {
nth,
current: 0,
with,
}),
}
}
}
impl<I> Iterator for ReplaceNth<I>
where
I: Iterator,
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
use self::ReplaceNthState as RNS;
let mut ret = self.iter.next()?;
let replace = match self.state {
RNS::Unreplaced(ref mut unreplaced) => {
let x = unreplaced.nth == unreplaced.current;
if !x {
unreplaced.current += 1
}
x
}
RNS::Replaced => false,
};
if replace {
if let RNS::Unreplaced(unreplaced) = mem::replace(&mut self.state, RNS::Replaced) {
ret = unreplaced.with;
}
}
Some(ret)
}
fn nth(&mut self, nth: usize) -> Option<I::Item> {
use self::ReplaceNthState as RNS;
let mut ret = self.iter.nth(nth)?;
let mut replace = Ordering::Greater;
if let RNS::Unreplaced(ref mut unreplaced) = self.state {
unreplaced.current += nth;
replace = unreplaced.current.cmp(&unreplaced.nth);
if replace == Ordering::Less {
unreplaced.current += 1;
}
}
match replace {
Ordering::Less => {}
Ordering::Equal => {
if let RNS::Unreplaced(unreplaced) = mem::replace(&mut self.state, RNS::Replaced) {
ret = unreplaced.with;
}
}
Ordering::Greater => self.state = RNS::Replaced,
}
Some(ret)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn count(self) -> usize {
self.iter.count()
}
}
#[cfg(test)]
#[cfg(feature = "alloc")]
mod test_replace_nth {
use super::*;
#[test]
fn nth_method() {
let list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for i in 0..list.len() {
let mut iter = ReplaceNth::new(list.iter().cloned(), i, 100);
if i != 0 {
let j = i - 1;
assert_eq!(iter.nth(j).unwrap(), list[j])
}
assert_eq!(iter.next().unwrap(), 100);
if i + 1 < list.len() {
assert_eq!(iter.next().unwrap(), list[i + 1]);
}
if i + 2 < list.len() {
assert_eq!(iter.next().unwrap(), list[i + 2]);
}
}
}
}
pub trait IteratorExt: Iterator {
#[inline(always)]
fn extending<C>(self, extend: &mut C)
where
Self: Sized,
C: Extend<Self::Item>,
{
extend.extend(self);
}
#[inline(always)]
fn collect_into<C>(self, mut extend: C) -> C
where
Self: Sized,
C: Extend<Self::Item>,
{
extend.extend(self);
extend
}
#[inline(always)]
fn replace_nth(self, nth: usize, with: Self::Item) -> ReplaceNth<Self>
where
Self: Sized,
{
ReplaceNth::new(self, nth, with)
}
#[inline]
fn sum_same(self) -> Self::Item
where
Self: Sized,
Self::Item: Sum,
{
<Self::Item as Sum<Self::Item>>::sum(self)
}
#[inline]
fn product_same(self) -> Self::Item
where
Self: Sized,
Self::Item: Product,
{
<Self::Item as Product<Self::Item>>::product(self)
}
}
impl<I> IteratorExt for I where I: ?Sized + Iterator {}
#[derive(Debug, Copy, Clone)]
pub struct IterConstructor<F> (pub F);
impl<F, I> IntoIterator for IterConstructor<F>
where
F: FnOnce() -> I,
I: IntoIterator,
{
type Item = I::Item;
type IntoIter = I::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
(self.0)().into_iter()
}
}
#[cfg(feature = "iterators")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iterators")))]
#[macro_export]
macro_rules! iter_cloner {
(let $ident:ident = $expr:expr) => {
let $ident = $crate::std_::iter::IntoIterator::into_iter($expr);
let $ident = $crate::iterators::IterCloner(&$ident);
};
}
#[derive(Debug)]
pub struct IterCloner<'a, I: 'a> (pub &'a I);
impl<'a, I> Copy for IterCloner<'a, I> {}
impl<'a, I> Clone for IterCloner<'a, I> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, I: 'a> IntoIterator for IterCloner<'a, I>
where
I: Iterator + Clone,
{
type Item = I::Item;
type IntoIter = I;
fn into_iter(self) -> Self::IntoIter {
self.0.clone()
}
}