Skip to content

Commit c220bdb

Browse files
committed
Add core::iter::adapters::PeekMap and core::iter::Peekable::peek_map
1 parent 475f6f8 commit c220bdb

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

library/core/src/iter/adapters/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod intersperse;
1818
mod map;
1919
mod map_while;
2020
mod map_windows;
21+
mod peek_map;
2122
mod peekable;
2223
mod rev;
2324
mod scan;
@@ -31,8 +32,9 @@ mod zip;
3132
#[stable(feature = "rust1", since = "1.0.0")]
3233
pub use self::{
3334
chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap,
34-
flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peekable::Peekable, rev::Rev,
35-
scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip,
35+
flatten::FlatMap, fuse::Fuse, inspect::Inspect, map::Map, peek_map::PeekMap,
36+
peekable::Peekable, rev::Rev, scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take,
37+
take_while::TakeWhile, zip::Zip,
3638
};
3739

3840
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
2+
use crate::iter::{FusedIterator, InPlaceIterable, Peekable, TrustedFused, TrustedLen};
3+
use crate::num::NonZeroUsize;
4+
5+
/// An iterator that maps the values of `iter` with `f`.
6+
#[must_use = "iterators are lazy and do nothing unless consumed"]
7+
#[stable(feature = "rust1", since = "1.0.0")]
8+
pub struct PeekMap<P, F> {
9+
pub(crate) peekable: P,
10+
f: F,
11+
}
12+
13+
impl<I: Iterator, F> PeekMap<Peekable<I>, F> {
14+
pub(in crate::iter) fn new(peekable: Peekable<I>, f: F) -> PeekMap<Peekable<I>, F> {
15+
PeekMap { peekable, f }
16+
}
17+
}
18+
19+
#[stable(feature = "rust1", since = "1.0.0")]
20+
impl<B, I: Iterator, F> Iterator for PeekMap<Peekable<I>, F>
21+
where
22+
F: FnMut(I::Item, Option<&I::Item>) -> B,
23+
{
24+
type Item = B;
25+
26+
#[inline]
27+
fn next(&mut self) -> Option<B> {
28+
self.peekable.next().map(|f| (f, self.peekable.peek())).map(&mut self.f)
29+
}
30+
31+
#[inline]
32+
fn size_hint(&self) -> (usize, Option<usize>) {
33+
self.peekable.size_hint()
34+
}
35+
}
36+
37+
#[stable(feature = "rust1", since = "1.0.0")]
38+
impl<B, I: ExactSizeIterator, F> ExactSizeIterator for PeekMap<Peekable<I>, F>
39+
where
40+
F: FnMut(I::Item, Option<&I::Item>) -> B,
41+
{
42+
fn len(&self) -> usize {
43+
self.peekable.len()
44+
}
45+
46+
fn is_empty(&self) -> bool {
47+
self.peekable.is_empty()
48+
}
49+
}
50+
51+
#[stable(feature = "fused", since = "1.26.0")]
52+
impl<B, I: FusedIterator, F> FusedIterator for PeekMap<Peekable<I>, F> where
53+
F: FnMut(I::Item, Option<&I::Item>) -> B
54+
{
55+
}
56+
57+
#[unstable(issue = "none", feature = "trusted_fused")]
58+
unsafe impl<I: Iterator, F> TrustedFused for PeekMap<Peekable<I>, F> where I: TrustedFused {}
59+
60+
#[unstable(feature = "trusted_len", issue = "37572")]
61+
unsafe impl<B, I, F> TrustedLen for PeekMap<Peekable<I>, F>
62+
where
63+
I: TrustedLen,
64+
F: FnMut(I::Item, Option<&I::Item>) -> B,
65+
{
66+
}
67+
68+
#[doc(hidden)]
69+
#[unstable(feature = "trusted_random_access", issue = "none")]
70+
unsafe impl<I: Iterator, F> TrustedRandomAccess for PeekMap<Peekable<I>, F> where
71+
I: TrustedRandomAccess
72+
{
73+
}
74+
75+
#[doc(hidden)]
76+
#[unstable(feature = "trusted_random_access", issue = "none")]
77+
unsafe impl<I, F> TrustedRandomAccessNoCoerce for PeekMap<Peekable<I>, F>
78+
where
79+
I: TrustedRandomAccessNoCoerce,
80+
{
81+
const MAY_HAVE_SIDE_EFFECT: bool = true;
82+
}
83+
84+
#[unstable(issue = "none", feature = "inplace_iteration")]
85+
unsafe impl<I: Iterator, F> SourceIter for PeekMap<Peekable<I>, F>
86+
where
87+
I: SourceIter,
88+
{
89+
type Source = I::Source;
90+
91+
#[inline]
92+
unsafe fn as_inner(&mut self) -> &mut I::Source {
93+
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
94+
unsafe { SourceIter::as_inner(&mut self.peekable.as_inner()) }
95+
}
96+
}
97+
98+
#[unstable(issue = "none", feature = "inplace_iteration")]
99+
unsafe impl<I: Iterator, F> InPlaceIterable for PeekMap<Peekable<I>, F>
100+
where
101+
I: InPlaceIterable,
102+
{
103+
const EXPAND_BY: Option<NonZeroUsize> = I::EXPAND_BY;
104+
const MERGE_BY: Option<NonZeroUsize> = I::MERGE_BY;
105+
}

library/core/src/iter/adapters/peekable.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen};
1+
use crate::iter::{adapters::PeekMap, adapters::SourceIter, FusedIterator, TrustedLen};
22
use crate::ops::{ControlFlow, Try};
33

44
/// An iterator with a `peek()` that returns an optional reference to the next
@@ -316,6 +316,14 @@ impl<I: Iterator> Peekable<I> {
316316
{
317317
self.next_if(|next| next == expected)
318318
}
319+
320+
#[unstable(feature = "peek_map", issue = "118474")]
321+
pub fn peek_map<B, F>(self, f: F) -> PeekMap<Self, F>
322+
where
323+
F: FnMut(I::Item, Option<&I::Item>) -> B,
324+
{
325+
PeekMap::new(self, f)
326+
}
319327
}
320328

321329
#[unstable(feature = "trusted_len", issue = "37572")]

0 commit comments

Comments
 (0)