diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-11-26 09:44:06 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-11-26 16:49:35 -0800 |
| commit | 74f0ceba6c956e8a332993db8dd667de3c461aa2 (patch) | |
| tree | 001757366faddadec046607182646261f905635a | |
| parent | 97495da163c017da34ce2bc8ba31388524216ba1 (diff) | |
| parent | 865c2dba30cee0d61ca0073aaf5fd32587887674 (diff) | |
| download | rust-74f0ceba6c956e8a332993db8dd667de3c461aa2.tar.gz rust-74f0ceba6c956e8a332993db8dd667de3c461aa2.zip | |
rollup merge of #19231: Gankro/ringbuf-into-iter
r? @huonw @csherratt
| -rw-r--r-- | src/libcollections/ring_buf.rs | 110 |
1 files changed, 102 insertions, 8 deletions
diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 8f0b0d41b03..e719a6c6da3 100644 --- a/src/libcollections/ring_buf.rs +++ b/src/libcollections/ring_buf.rs @@ -34,8 +34,6 @@ static MINIMUM_CAPACITY: uint = 2u; // FIXME(conventions): implement shrink_to_fit. Awkward with the current design, but it should // be scrapped anyway. Defer to rewrite? -// FIXME(conventions): implement into_iter - /// `RingBuf` is a circular buffer that implements `Deque`. pub struct RingBuf<T> { @@ -394,6 +392,14 @@ impl<T> RingBuf<T> { } } + /// Consumes the list into an iterator yielding elements by value. + #[unstable = "matches collection reform specification, waiting for dust to settle"] + pub fn into_iter(self) -> MoveItems<T> { + MoveItems { + inner: self, + } + } + /// Returns the number of elements in the `RingBuf`. /// /// # Example @@ -736,11 +742,9 @@ impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> { } let tail = self.tail; self.tail = wrap_index(self.tail + 1, self.cap); - if mem::size_of::<T>() != 0 { - unsafe { Some(&mut *self.ptr.offset(tail as int)) } - } else { - // use a non-zero pointer - Some(unsafe { mem::transmute(1u) }) + + unsafe { + Some(&mut *self.ptr.offset(tail as int)) } } @@ -758,12 +762,43 @@ impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> { return None; } self.head = wrap_index(self.head - 1, self.cap); - unsafe { Some(&mut *self.ptr.offset(self.head as int)) } + + unsafe { + Some(&mut *self.ptr.offset(self.head as int)) + } } } impl<'a, T> ExactSizeIterator<&'a mut T> for MutItems<'a, T> {} +// A by-value RingBuf iterator +pub struct MoveItems<T> { + inner: RingBuf<T>, +} + +impl<T> Iterator<T> for MoveItems<T> { + #[inline] + fn next(&mut self) -> Option<T> { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (uint, Option<uint>) { + let len = self.inner.len(); + (len, Some(len)) + } +} + +impl<T> DoubleEndedIterator<T> for MoveItems<T> { + #[inline] + fn next_back(&mut self) -> Option<T> { + self.inner.pop_back() + } +} + + +impl<T> ExactSize<T> for MoveItems<T> {} + impl<A: PartialEq> PartialEq for RingBuf<A> { fn eq(&self, other: &RingBuf<A>) -> bool { self.len() == other.len() && @@ -1314,6 +1349,65 @@ mod tests { } #[test] + fn test_into_iter() { + + // Empty iter + { + let d: RingBuf<int> = RingBuf::new(); + let mut iter = d.into_iter(); + + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + // simple iter + { + let mut d = RingBuf::new(); + for i in range(0i, 5) { + d.push_back(i); + } + + let b = vec![0,1,2,3,4]; + assert_eq!(d.into_iter().collect::<Vec<int>>(), b); + } + + // wrapped iter + { + let mut d = RingBuf::new(); + for i in range(0i, 5) { + d.push_back(i); + } + for i in range(6, 9) { + d.push_front(i); + } + + let b = vec![8,7,6,0,1,2,3,4]; + assert_eq!(d.into_iter().collect::<Vec<int>>(), b); + } + + // partially used + { + let mut d = RingBuf::new(); + for i in range(0i, 5) { + d.push_back(i); + } + for i in range(6, 9) { + d.push_front(i); + } + + let mut it = d.into_iter(); + assert_eq!(it.size_hint(), (8, Some(8))); + assert_eq!(it.next(), Some(8)); + assert_eq!(it.size_hint(), (7, Some(7))); + assert_eq!(it.next_back(), Some(4)); + assert_eq!(it.size_hint(), (6, Some(6))); + assert_eq!(it.next(), Some(7)); + assert_eq!(it.size_hint(), (5, Some(5))); + } + } + + #[test] fn test_from_iter() { use std::iter; let v = vec!(1i,2,3,4,5,6,7); |
