about summary refs log tree commit diff
path: root/src/libcoretest
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-11-22 03:29:46 -0600
committerGitHub <noreply@github.com>2016-11-22 03:29:46 -0600
commit0f7c75b74fb7adc436eedc66c0032879293eeac6 (patch)
tree2b34cfc1fa6076cbe90a38091e4ba478f92117d2 /src/libcoretest
parent1c11ea3aedebac562f5125e1cf22ac56a3a8993c (diff)
parent6c2a456bf198e7853f570435fc78bbd99c51b9d6 (diff)
downloadrust-0f7c75b74fb7adc436eedc66c0032879293eeac6.tar.gz
rust-0f7c75b74fb7adc436eedc66c0032879293eeac6.zip
Auto merge of #37834 - bluss:peek-none, r=BurntSushi
Make Peekable remember peeking a None

Peekable should remember if a None has been seen in the `.peek()` method.
It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
underlying iterator at most once. This does not by itself make the iterator
fused.

Thanks to @s3bk for the code in `fn peek()` itself.

Fixes #37784
Diffstat (limited to 'src/libcoretest')
-rw-r--r--src/libcoretest/iter.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index 58b6444ef88..274539dfa66 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -274,6 +274,74 @@ fn test_iterator_peekable_last() {
     let mut it = ys.iter().peekable();
     assert_eq!(it.peek(), Some(&&0));
     assert_eq!(it.last(), Some(&0));
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.next(), Some(&0));
+    assert_eq!(it.peek(), None);
+    assert_eq!(it.last(), None);
+}
+
+/// This is an iterator that follows the Iterator contract,
+/// but it is not fused. After having returned None once, it will start
+/// producing elements if .next() is called again.
+pub struct CycleIter<'a, T: 'a> {
+    index: usize,
+    data: &'a [T],
+}
+
+pub fn cycle<T>(data: &[T]) -> CycleIter<T> {
+    CycleIter {
+        index: 0,
+        data: data,
+    }
+}
+
+impl<'a, T> Iterator for CycleIter<'a, T> {
+    type Item = &'a T;
+    fn next(&mut self) -> Option<Self::Item> {
+        let elt = self.data.get(self.index);
+        self.index += 1;
+        self.index %= 1 + self.data.len();
+        elt
+    }
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_1() {
+    // Check that the loop using .peek() terminates
+    let data = [1, 2, 3];
+    let mut iter = cycle(&data).peekable();
+
+    let mut n = 0;
+    while let Some(_) = iter.next() {
+        let is_the_last = iter.peek().is_none();
+        assert_eq!(is_the_last, n == data.len() - 1);
+        n += 1;
+        if n > data.len() { break; }
+    }
+    assert_eq!(n, data.len());
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_2() {
+    let data = [0];
+    let mut iter = cycle(&data).peekable();
+    iter.next();
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.last(), None);
+}
+
+#[test]
+fn test_iterator_peekable_remember_peek_none_3() {
+    let data = [0];
+    let mut iter = cycle(&data).peekable();
+    iter.peek();
+    assert_eq!(iter.nth(0), Some(&0));
+
+    let mut iter = cycle(&data).peekable();
+    iter.next();
+    assert_eq!(iter.peek(), None);
+    assert_eq!(iter.nth(0), None);
 }
 
 #[test]