Skip to content

Commit 2e68403

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

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

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

Lines changed: 8 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,13 @@ impl<I: Iterator> Peekable<I> {
316316
{
317317
self.next_if(|next| next == expected)
318318
}
319+
320+
pub fn peek_map<F>(self, f: F) -> PeekMap<Self, F>
321+
where
322+
F: FnMut(I::Item, Option<&I::Item>) -> B,
323+
{
324+
PeekMap::new(self, f)
325+
}
319326
}
320327

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

0 commit comments

Comments
 (0)