From 865c2dba30cee0d61ca0073aaf5fd32587887674 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Sat, 22 Nov 2014 21:34:11 -0500 Subject: [PATCH] add MoveItems to RingBuf, fixes #19085 --- src/libcollections/ring_buf.rs | 110 ++++++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 8 deletions(-) diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs index 643b500ec3e..78e0bb19b4c 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 { @@ -394,6 +392,14 @@ impl RingBuf { } } + /// 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 { + MoveItems { + inner: self, + } + } + /// Returns the number of elements in the `RingBuf`. /// /// # Example @@ -737,11 +743,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::() != 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)) } } @@ -759,12 +763,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> ExactSize<&'a mut T> for MutItems<'a, T> {} +// A by-value RingBuf iterator +pub struct MoveItems { + inner: RingBuf, +} + +impl Iterator for MoveItems { + #[inline] + fn next(&mut self) -> Option { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (uint, Option) { + let len = self.inner.len(); + (len, Some(len)) + } +} + +impl DoubleEndedIterator for MoveItems { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.pop_back() + } +} + + +impl ExactSize for MoveItems {} + impl PartialEq for RingBuf { fn eq(&self, other: &RingBuf) -> bool { self.len() == other.len() && @@ -1314,6 +1349,65 @@ mod tests { } } + #[test] + fn test_into_iter() { + + // Empty iter + { + let d: RingBuf = 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::>(), 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::>(), 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;