Skip to content

Commit deb7b67

Browse files
SimonSapinblake2-ppc
authored and
blake2-ppc
committed
Add a "peekable" iterator adaptor, with a peek() method that returns the next element.
1 parent b44f423 commit deb7b67

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

src/libstd/iterator.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,28 @@ pub trait Iterator<A> {
156156
Enumerate{iter: self, count: 0}
157157
}
158158

159+
160+
/// Creates an iterator that has a `.peek()` method
161+
/// that returns a optional reference to the next element.
162+
///
163+
/// # Example
164+
///
165+
/// ~~~ {.rust}
166+
/// let a = [100, 200, 300];
167+
/// let mut it = xs.iter().map(|&x|x).peekable();
168+
/// assert_eq!(it.peek().unwrap(), &100);
169+
/// assert_eq!(it.next().unwrap(), 100);
170+
/// assert_eq!(it.next().unwrap(), 200);
171+
/// assert_eq!(it.peek().unwrap(), &300);
172+
/// assert_eq!(it.peek().unwrap(), &300);
173+
/// assert_eq!(it.next().unwrap(), 300);
174+
/// assert!(it.peek().is_none());
175+
/// assert!(it.next().is_none());
176+
/// ~~~
177+
fn peekable(self) -> Peekable<A, Self> {
178+
Peekable{iter: self, peeked: None}
179+
}
180+
159181
/// Creates an iterator which invokes the predicate on elements until it
160182
/// returns false. Once the predicate returns false, all further elements are
161183
/// yielded.
@@ -1059,6 +1081,38 @@ impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<(uint, A)> for Enumerat
10591081
}
10601082
}
10611083

1084+
/// An iterator with a `peek()` that returns an optional reference to the next element.
1085+
pub struct Peekable<A, T> {
1086+
priv iter: T,
1087+
priv peeked: Option<A>,
1088+
}
1089+
1090+
impl<A, T: Iterator<A>> Iterator<A> for Peekable<A, T> {
1091+
#[inline]
1092+
fn next(&mut self) -> Option<A> {
1093+
if self.peeked.is_some() { self.peeked.take() }
1094+
else { self.iter.next() }
1095+
}
1096+
}
1097+
1098+
impl<'self, A, T: Iterator<A>> Peekable<A, T> {
1099+
/// Return a reference to the next element of the iterator with out advancing it,
1100+
/// or None if the iterator is exhausted.
1101+
#[inline]
1102+
pub fn peek(&'self mut self) -> Option<&'self A> {
1103+
match self.peeked {
1104+
Some(ref value) => Some(value),
1105+
None => {
1106+
self.peeked = self.iter.next();
1107+
match self.peeked {
1108+
Some(ref value) => Some(value),
1109+
None => None,
1110+
}
1111+
},
1112+
}
1113+
}
1114+
}
1115+
10621116
/// An iterator which rejects elements while `predicate` is true
10631117
pub struct SkipWhile<'self, A, T> {
10641118
priv iter: T,
@@ -1568,6 +1622,24 @@ mod tests {
15681622
}
15691623
}
15701624

1625+
#[test]
1626+
fn test_iterator_peekable() {
1627+
let xs = ~[0u, 1, 2, 3, 4, 5];
1628+
let mut it = xs.iter().map(|&x|x).peekable();
1629+
assert_eq!(it.peek().unwrap(), &0);
1630+
assert_eq!(it.next().unwrap(), 0);
1631+
assert_eq!(it.next().unwrap(), 1);
1632+
assert_eq!(it.next().unwrap(), 2);
1633+
assert_eq!(it.peek().unwrap(), &3);
1634+
assert_eq!(it.peek().unwrap(), &3);
1635+
assert_eq!(it.next().unwrap(), 3);
1636+
assert_eq!(it.next().unwrap(), 4);
1637+
assert_eq!(it.peek().unwrap(), &5);
1638+
assert_eq!(it.next().unwrap(), 5);
1639+
assert!(it.peek().is_none());
1640+
assert!(it.next().is_none());
1641+
}
1642+
15711643
#[test]
15721644
fn test_iterator_take_while() {
15731645
let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];

0 commit comments

Comments
 (0)