diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index a691039c789c6..fb1ed26d4acd8 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -18,6 +18,7 @@ mod intersperse; mod map; mod map_while; mod map_windows; +mod peek_map; mod peekable; mod rev; mod scan; @@ -31,8 +32,9 @@ mod zip; #[stable(feature = "rust1", since = "1.0.0")] pub use self::{ chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap, - flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peekable::Peekable, rev::Rev, - scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip, + flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peek_map::PeekMap, + peekable::Peekable, rev::Rev, scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, + take_while::TakeWhile, zip::Zip, }; #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] diff --git a/library/core/src/iter/adapters/peek_map.rs b/library/core/src/iter/adapters/peek_map.rs new file mode 100644 index 0000000000000..df65d4fd5001f --- /dev/null +++ b/library/core/src/iter/adapters/peek_map.rs @@ -0,0 +1,74 @@ +use crate::iter::{FusedIterator, Peekable}; + +/// An iterator that maps the values of `iter` with `f`. +/// +/// This struct is created by the [`peek_map`] method on [`Peekable`]. See its +/// documentation for more. +/// +/// [`peek_map`]: Peekable::peek_map +/// [`Peekable`]: struct.Peekable.html +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(peek_map)] +/// +/// let a = [1, 2, 3]; +/// let mut iter = a.into_iter().peekable().peek_map(|x, next| x * *next.unwrap_or(&1)); +/// +/// assert_eq!(iter.next(), Some(2)); +/// assert_eq!(iter.next(), Some(6)); +/// assert_eq!(iter.next(), Some(3)); +/// assert_eq!(iter.next(), None); +/// ``` +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "peek_map", issue = "118474")] +#[derive(Debug)] +pub struct PeekMap { + pub(crate) t: T, + f: F, +} + +impl PeekMap, F> { + pub(in crate::iter) fn new(peekable: Peekable, f: F) -> PeekMap, F> { + PeekMap { t: peekable, f } + } +} + +#[unstable(feature = "peek_map", issue = "118474")] +impl Iterator for PeekMap, F> +where + F: FnMut(I::Item, Option<&I::Item>) -> B, +{ + type Item = B; + + #[inline] + fn next(&mut self) -> Option { + Some((&mut self.f)(self.t.next()?, self.t.peek())) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.t.size_hint() + } +} +#[unstable(feature = "peek_map", issue = "118474")] +impl ExactSizeIterator for PeekMap, F> +where + F: FnMut(I::Item, Option<&I::Item>) -> B, +{ + fn len(&self) -> usize { + self.t.len() + } + + fn is_empty(&self) -> bool { + self.t.is_empty() + } +} +#[unstable(feature = "peek_map", issue = "118474")] +impl FusedIterator for PeekMap, F> where + F: FnMut(I::Item, Option<&I::Item>) -> B +{ +} diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 65ba42920c93d..b26699b4317b6 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,4 +1,4 @@ -use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen}; +use crate::iter::{adapters::PeekMap, adapters::SourceIter, FusedIterator, TrustedLen}; use crate::ops::{ControlFlow, Try}; /// An iterator with a `peek()` that returns an optional reference to the next @@ -316,6 +316,15 @@ impl Peekable { { self.next_if(|next| next == expected) } + + /// Honestly I'm adding this doc to get rid of the error just to make sure everything else actually works. + #[unstable(feature = "peek_map", issue = "118474")] + pub fn peek_map(self, f: F) -> PeekMap + where + F: FnMut(I::Item, Option<&I::Item>) -> B, + { + PeekMap::new(self, f) + } } #[unstable(feature = "trusted_len", issue = "37572")]