diff options
| author | bors <bors@rust-lang.org> | 2016-11-22 03:29:46 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-22 03:29:46 -0600 |
| commit | 0f7c75b74fb7adc436eedc66c0032879293eeac6 (patch) | |
| tree | 2b34cfc1fa6076cbe90a38091e4ba478f92117d2 /src/libcoretest | |
| parent | 1c11ea3aedebac562f5125e1cf22ac56a3a8993c (diff) | |
| parent | 6c2a456bf198e7853f570435fc78bbd99c51b9d6 (diff) | |
| download | rust-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.rs | 68 |
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] |
