Skip to content

Commit 5ab3c2f

Browse files
committed
Add PeekableIterator trait as an experiment
1 parent 3c17c84 commit 5ab3c2f

File tree

14 files changed

+251
-12
lines changed

14 files changed

+251
-12
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::iter::adapters::{
22
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
33
};
4-
use crate::iter::{FusedIterator, TrustedLen};
4+
use crate::iter::{FusedIterator, PeekableIterator, TrustedLen};
55
use crate::ops::Try;
66

77
/// An iterator that copies the elements of an underlying iterator.
@@ -139,6 +139,17 @@ where
139139
}
140140
}
141141

142+
#[unstable(feature = "peekable_iterator", issue = "none")]
143+
impl<'a, I, T: 'a> PeekableIterator for Copied<I>
144+
where
145+
I: PeekableIterator<Item = &'a T>,
146+
T: Copy,
147+
{
148+
fn peek(&self) -> Option<T> {
149+
self.it.peek().map(|x| *x)
150+
}
151+
}
152+
142153
#[stable(feature = "iter_copied", since = "1.36.0")]
143154
impl<'a, I, T: 'a> FusedIterator for Copied<I>
144155
where

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{iter::FusedIterator, ops::Try};
1+
use crate::{
2+
iter::{FusedIterator, PeekableIterator},
3+
ops::Try,
4+
};
25

36
/// An iterator that repeats endlessly.
47
///
@@ -104,5 +107,15 @@ where
104107
// and we can't do anything better than the default.
105108
}
106109

110+
#[unstable(feature = "peekable_iterator", issue = "none")]
111+
impl<I> PeekableIterator for Cycle<I>
112+
where
113+
I: Clone + PeekableIterator,
114+
{
115+
fn peek(&self) -> Option<I::Item> {
116+
self.iter.peek().or_else(|| self.orig.peek())
117+
}
118+
}
119+
107120
#[stable(feature = "fused", since = "1.26.0")]
108121
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::iter::adapters::{
22
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
33
};
4-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
4+
use crate::iter::{FusedIterator, InPlaceIterable, PeekableIterator, TrustedLen};
55
use crate::ops::Try;
66

77
/// An iterator that yields the current count and the element during iteration.
@@ -229,6 +229,16 @@ where
229229
}
230230
}
231231

232+
#[stable(feature = "rust1", since = "1.0.0")]
233+
impl<I> PeekableIterator for Enumerate<I>
234+
where
235+
I: PeekableIterator,
236+
{
237+
fn peek(&self) -> Option<(usize, I::Item)> {
238+
self.iter.peek().map(|x| (self.count, x))
239+
}
240+
}
241+
232242
#[doc(hidden)]
233243
#[unstable(feature = "trusted_random_access", issue = "none")]
234244
unsafe impl<I> TrustedRandomAccess for Enumerate<I> where I: TrustedRandomAccess {}

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::intrinsics;
22
use crate::iter::adapters::zip::try_get_unchecked;
33
use crate::iter::{
4-
DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess,
5-
TrustedRandomAccessNoCoerce,
4+
DoubleEndedIterator, ExactSizeIterator, FusedIterator, PeekableIterator, TrustedLen,
5+
TrustedRandomAccess, TrustedRandomAccessNoCoerce,
66
};
77
use crate::ops::Try;
88

@@ -26,6 +26,16 @@ impl<I> Fuse<I> {
2626
}
2727
}
2828

29+
#[unstable(feature = "peekable_iterator", issue = "none")]
30+
impl<I> PeekableIterator for Fuse<I>
31+
where
32+
I: PeekableIterator,
33+
{
34+
fn peek(&self) -> Option<I::Item> {
35+
self.iter.as_ref().and_then(|iter| iter.peek())
36+
}
37+
}
38+
2939
#[stable(feature = "fused", since = "1.26.0")]
3040
impl<I> FusedIterator for Fuse<I> where I: Iterator {}
3141

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::fmt;
2-
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
2+
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, PeekableIterator};
33
use crate::ops::Try;
44

55
/// An iterator that calls a function with a reference to each element before
@@ -145,6 +145,16 @@ where
145145
}
146146
}
147147

148+
#[unstable(feature = "peekable_iterator", issue = "none")]
149+
impl<I: PeekableIterator, F> PeekableIterator for Inspect<I, F>
150+
where
151+
F: FnMut(&I::Item),
152+
{
153+
fn peek(&self) -> Option<I::Item> {
154+
self.iter.peek()
155+
}
156+
}
157+
148158
#[stable(feature = "fused", since = "1.26.0")]
149159
impl<I: FusedIterator, F> FusedIterator for Inspect<I, F> where F: FnMut(&I::Item) {}
150160

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::cmp;
2-
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
2+
use crate::iter::{
3+
adapters::SourceIter, FusedIterator, InPlaceIterable, PeekableIterator, TrustedLen,
4+
};
35
use crate::ops::{ControlFlow, Try};
46

57
/// An iterator that only iterates over the first `n` iterations of `iter`.
@@ -237,6 +239,16 @@ where
237239
#[stable(feature = "rust1", since = "1.0.0")]
238240
impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
239241

242+
#[unstable(feature = "peekable_iterator", issue = "none")]
243+
impl<I> PeekableIterator for Take<I>
244+
where
245+
I: PeekableIterator,
246+
{
247+
fn peek(&self) -> Option<I::Item> {
248+
if self.n == 0 { None } else { self.iter.peek() }
249+
}
250+
}
251+
240252
#[stable(feature = "fused", since = "1.26.0")]
241253
impl<I> FusedIterator for Take<I> where I: FusedIterator {}
242254

library/core/src/iter/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ pub use self::sources::{successors, Successors};
382382
pub use self::traits::FusedIterator;
383383
#[unstable(issue = "none", feature = "inplace_iteration")]
384384
pub use self::traits::InPlaceIterable;
385+
#[unstable(feature = "peekable_iterator", issue = "none")]
386+
pub use self::traits::PeekableIterator;
385387
#[unstable(feature = "trusted_len", issue = "37572")]
386388
pub use self::traits::TrustedLen;
387389
#[unstable(feature = "trusted_step", issue = "85731")]

library/core/src/iter/range.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use crate::mem;
44
use crate::ops::{self, Try};
55

66
use super::{
7-
FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep,
7+
FusedIterator, PeekableIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
8+
TrustedStep,
89
};
910

1011
// Safety: All invariants are upheld.
@@ -765,6 +766,13 @@ impl<A: Step> Iterator for ops::Range<A> {
765766
}
766767
}
767768

769+
#[unstable(feature = "peekable_iterator", issue = "none")]
770+
impl<A: Step> PeekableIterator for ops::Range<A> {
771+
fn peek(&self) -> Option<A> {
772+
if self.start < self.end { Some(self.start.clone()) } else { None }
773+
}
774+
}
775+
768776
// These macros generate `ExactSizeIterator` impls for various range types.
769777
//
770778
// * `ExactSizeIterator::len` is required to always return an exact `usize`,
@@ -879,6 +887,13 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
879887
}
880888
}
881889

890+
#[unstable(feature = "peekable_iterator", issue = "none")]
891+
impl<A: Step> PeekableIterator for ops::RangeFrom<A> {
892+
fn peek(&self) -> Option<A> {
893+
Some(self.start.clone())
894+
}
895+
}
896+
882897
// Safety: See above implementation for `ops::Range<A>`
883898
#[unstable(feature = "trusted_len", issue = "37572")]
884899
unsafe impl<A: TrustedStep> TrustedLen for ops::RangeFrom<A> {}
@@ -1186,6 +1201,13 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
11861201
}
11871202
}
11881203

1204+
#[unstable(feature = "peekable_iterator", issue = "none")]
1205+
impl<A: Step> PeekableIterator for ops::RangeInclusive<A> {
1206+
fn peek(&self) -> Option<A> {
1207+
if self.is_empty() { None } else { Some(self.start.clone()) }
1208+
}
1209+
}
1210+
11891211
#[stable(feature = "inclusive_range", since = "1.26.0")]
11901212
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
11911213
#[inline]

library/core/src/iter/sources/empty.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::fmt;
2-
use crate::iter::{FusedIterator, TrustedLen};
2+
use crate::iter::{FusedIterator, PeekableIterator, TrustedLen};
33
use crate::marker;
44

55
/// Creates an iterator that yields nothing.
@@ -68,6 +68,13 @@ impl<T> ExactSizeIterator for Empty<T> {
6868
}
6969
}
7070

71+
#[unstable(feature = "peekable_iterator", issue = "none")]
72+
impl<T> PeekableIterator for Empty<T> {
73+
fn peek(&self) -> Option<T> {
74+
None
75+
}
76+
}
77+
7178
#[unstable(feature = "trusted_len", issue = "37572")]
7279
unsafe impl<T> TrustedLen for Empty<T> {}
7380

library/core/src/iter/sources/once.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::iter::{FusedIterator, TrustedLen};
1+
use crate::iter::{FusedIterator, PeekableIterator, TrustedLen};
22

33
/// Creates an iterator that yields an element exactly once.
44
///
@@ -92,6 +92,13 @@ impl<T> ExactSizeIterator for Once<T> {
9292
}
9393
}
9494

95+
#[unstable(feature = "peekable_iterator", issue = "none")]
96+
impl<T: Clone> PeekableIterator for Once<T> {
97+
fn peek(&self) -> Option<T> {
98+
self.inner.peek()
99+
}
100+
}
101+
95102
#[unstable(feature = "trusted_len", issue = "37572")]
96103
unsafe impl<T> TrustedLen for Once<T> {}
97104

0 commit comments

Comments
 (0)