diff --git a/src/adaptors/map.rs b/src/adaptors/map.rs index cf5e5a00d..dae48bd8d 100644 --- a/src/adaptors/map.rs +++ b/src/adaptors/map.rs @@ -1,3 +1,4 @@ +use core::iter::Peekable; use std::iter::FromIterator; use std::marker::PhantomData; @@ -122,3 +123,41 @@ pub fn map_into(iter: I) -> MapInto { f: MapSpecialCaseFnInto(PhantomData), } } + +#[must_use = "iterator adaptors are lazy and do nothing unless consumed"] +pub struct PeekMap +where + I: Iterator, + F: FnMut(I::Item, Option<&I::Item>) -> U, +{ + iter: Peekable, + f: F, +} + +impl Iterator for PeekMap +where + I: Iterator, + F: FnMut(I::Item, Option<&I::Item>) -> U, +{ + type Item = U; + + fn next(&mut self) -> Option { + Some((self.f)(self.iter.next()?, self.iter.peek())) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +/// Create a new `PeekMap` iterator. +pub fn peek_map(iter: I, f: F) -> PeekMap +where + I: Iterator, + F: FnMut(I::Item, Option<&I::Item>) -> U, +{ + PeekMap { + iter: iter.peekable(), + f, + } +} diff --git a/src/adaptors/mod.rs b/src/adaptors/mod.rs index e925db51d..2ce49fad0 100644 --- a/src/adaptors/mod.rs +++ b/src/adaptors/mod.rs @@ -10,7 +10,7 @@ mod multi_product; pub use self::coalesce::*; #[allow(deprecated)] pub use self::map::MapResults; -pub use self::map::{map_into, map_ok, MapInto, MapOk}; +pub use self::map::{map_into, map_ok, peek_map, MapInto, MapOk, PeekMap}; #[cfg(feature = "use_alloc")] pub use self::multi_product::*; diff --git a/src/lib.rs b/src/lib.rs index bdb436e48..df3580b82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -84,8 +84,8 @@ pub mod structs { pub use crate::adaptors::MultiProduct; pub use crate::adaptors::{ Batching, Coalesce, Dedup, DedupBy, DedupByWithCount, DedupWithCount, FilterMapOk, - FilterOk, Interleave, InterleaveShortest, MapInto, MapOk, Positions, Product, PutBack, - TakeWhileRef, TupleCombinations, Update, WhileSome, + FilterOk, Interleave, InterleaveShortest, MapInto, MapOk, PeekMap, Positions, Product, + PutBack, TakeWhileRef, TupleCombinations, Update, WhileSome, }; #[allow(deprecated)] pub use crate::adaptors::{MapResults, Step}; @@ -3964,6 +3964,14 @@ pub trait Itertools: Iterator { _ => Err(sh), } } + + fn peek_map(self, f: F) -> PeekMap + where + Self: Sized, + F: FnMut(Self::Item, Option<&Self::Item>) -> B, + { + adaptors::peek_map(self, f) + } } impl Itertools for T where T: Iterator {}