Skip to content

Commit 93fd52b

Browse files
committed
implement drain
1 parent dfd78d1 commit 93fd52b

File tree

1 file changed

+110
-25
lines changed

1 file changed

+110
-25
lines changed

lib.rs

Lines changed: 110 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,15 @@ use std::borrow::{Borrow, BorrowMut};
5555
use std::cmp;
5656
use std::fmt;
5757
use std::hash::{Hash, Hasher};
58-
use std::iter::{IntoIterator, FromIterator, repeat};
58+
use std::iter::{IntoIterator, FromIterator, FusedIterator, repeat};
5959
use std::mem;
6060
use std::mem::ManuallyDrop;
6161
use std::ops;
6262
use std::ptr;
63+
use std::fmt::Debug;
6364
use std::slice;
65+
use std::ops::{RangeBounds, Bound};
66+
use std::ptr::NonNull;
6467
#[cfg(feature = "std")]
6568
use std::io;
6669
#[cfg(feature = "serde")]
@@ -240,15 +243,32 @@ unsafe fn deallocate<T>(ptr: *mut T, capacity: usize) {
240243
/// Returned from [`SmallVec::drain`][1].
241244
///
242245
/// [1]: struct.SmallVec.html#method.drain
243-
pub struct Drain<'a, T: 'a> {
244-
iter: slice::IterMut<'a,T>,
246+
pub struct Drain<'a, T: 'a + Array> {
247+
tail_start: usize,
248+
tail_len: usize,
249+
iter: slice::Iter<'a, T::Item>,
250+
vec: NonNull<SmallVec<T>>
245251
}
246252

247-
impl<'a, T: 'a> Iterator for Drain<'a,T> {
248-
type Item = T;
253+
impl<'a, T: 'a + Array> fmt::Debug for Drain<'a, T>
254+
where T::Item: Debug
255+
{
256+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
257+
f.debug_tuple("Drain")
258+
.field(&self.iter.as_slice())
259+
.finish()
260+
}
261+
}
262+
263+
unsafe impl<'a, T: Sync + Array> Sync for Drain<'a, T> {}
264+
unsafe impl<'a, T: Send + Array> Send for Drain<'a, T> {}
265+
266+
267+
impl<'a, T: 'a + Array> Iterator for Drain<'a,T> {
268+
type Item = T::Item;
249269

250270
#[inline]
251-
fn next(&mut self) -> Option<T> {
271+
fn next(&mut self) -> Option<T::Item> {
252272
self.iter.next().map(|reference| unsafe { ptr::read(reference) })
253273
}
254274

@@ -258,19 +278,41 @@ impl<'a, T: 'a> Iterator for Drain<'a,T> {
258278
}
259279
}
260280

261-
impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
281+
impl<'a, T: 'a + Array> DoubleEndedIterator for Drain<'a, T> {
262282
#[inline]
263-
fn next_back(&mut self) -> Option<T> {
283+
fn next_back(&mut self) -> Option<T::Item> {
264284
self.iter.next_back().map(|reference| unsafe { ptr::read(reference) })
265285
}
266286
}
267287

268-
impl<'a, T> ExactSizeIterator for Drain<'a, T> { }
288+
impl<'a, T: Array> ExactSizeIterator for Drain<'a, T> {
289+
#[inline]
290+
fn len(&self) -> usize {
291+
self.iter.len()
292+
}
293+
}
269294

270-
impl<'a, T: 'a> Drop for Drain<'a,T> {
295+
impl<'a, T: Array> FusedIterator for Drain<'a, T> {}
296+
297+
impl<'a, T: 'a + Array> Drop for Drain<'a,T> {
271298
fn drop(&mut self) {
272-
// Destroy the remaining elements.
273-
for _ in self.by_ref() {}
299+
self.for_each(drop);
300+
301+
if self.tail_len > 0 {
302+
unsafe {
303+
let source_vec = self.vec.as_mut();
304+
305+
// memmove back untouched tail, update to new length
306+
let start = source_vec.len();
307+
let tail = self.tail_start;
308+
if tail != start {
309+
let src = source_vec.as_ptr().add(tail);
310+
let dst = source_vec.as_mut_ptr().add(start);
311+
ptr::copy(src, dst, self.tail_len);
312+
}
313+
source_vec.set_len(start + self.tail_len);
314+
}
315+
}
274316
}
275317
}
276318

@@ -596,18 +638,50 @@ impl<A: Array> SmallVec<A> {
596638
self.capacity > A::size()
597639
}
598640

599-
/// Empty the vector and return an iterator over its former contents.
600-
pub fn drain(&mut self) -> Drain<A::Item> {
601-
unsafe {
602-
let ptr = self.as_mut_ptr();
641+
/// Creates a draining iterator that removes the specified range in the vector
642+
/// and yields the removed items.
643+
///
644+
/// Note 1: The element range is removed even if the iterator is only
645+
/// partially consumed or not consumed at all.
646+
///
647+
/// Note 2: It is unspecified how many elements are removed from the vector
648+
/// if the `Drain` value is leaked.
649+
///
650+
/// # Panics
651+
///
652+
/// Panics if the starting point is greater than the end point or if
653+
/// the end point is greater than the length of the vector.
654+
pub fn drain<R>(&mut self, range: R) -> Drain<A>
655+
where R: RangeBounds<usize>
656+
{
657+
use Bound::*;
603658

604-
let current_len = self.len();
605-
self.set_len(0);
659+
let len = self.len();
660+
let start = match range.start_bound() {
661+
Included(&n) => n,
662+
Excluded(&n) => n + 1,
663+
Unbounded => 0,
664+
};
665+
let end = match range.end_bound() {
666+
Included(&n) => n + 1,
667+
Excluded(&n) => n,
668+
Unbounded => len,
669+
};
670+
671+
assert!(start <= end);
672+
assert!(end <= len);
673+
674+
unsafe {
675+
self.set_len(start);
606676

607-
let slice = slice::from_raw_parts_mut(ptr, current_len);
677+
let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start),
678+
end - start);
608679

609680
Drain {
610-
iter: slice.iter_mut(),
681+
tail_start: end,
682+
tail_len: len - end,
683+
iter: range_slice.iter(),
684+
vec: NonNull::from(self),
611685
}
612686
}
613687
}
@@ -1711,26 +1785,36 @@ mod tests {
17111785
fn drain() {
17121786
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
17131787
v.push(3);
1714-
assert_eq!(v.drain().collect::<Vec<_>>(), &[3]);
1788+
assert_eq!(v.drain(..).collect::<Vec<_>>(), &[3]);
17151789

17161790
// spilling the vec
17171791
v.push(3);
17181792
v.push(4);
17191793
v.push(5);
1720-
assert_eq!(v.drain().collect::<Vec<_>>(), &[3, 4, 5]);
1794+
let old_capacity = v.capacity();
1795+
assert_eq!(v.drain(1..).collect::<Vec<_>>(), &[4, 5]);
1796+
// drain should not change the capacity
1797+
assert_eq!(v.capacity(), old_capacity);
17211798
}
17221799

17231800
#[test]
17241801
fn drain_rev() {
17251802
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
17261803
v.push(3);
1727-
assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[3]);
1804+
assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[3]);
17281805

17291806
// spilling the vec
17301807
v.push(3);
17311808
v.push(4);
17321809
v.push(5);
1733-
assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[5, 4, 3]);
1810+
assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[5, 4, 3]);
1811+
}
1812+
1813+
#[test]
1814+
fn drain_forget() {
1815+
let mut v: SmallVec<[u8; 1]> = smallvec![0, 1, 2, 3, 4, 5, 6, 7];
1816+
std::mem::forget(v.drain(2..5));
1817+
assert_eq!(v.len(), 2);
17341818
}
17351819

17361820
#[test]
@@ -2125,7 +2209,8 @@ mod tests {
21252209
fn test_exact_size_iterator() {
21262210
let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);
21272211
assert_eq!(vec.clone().into_iter().len(), 3);
2128-
assert_eq!(vec.drain().len(), 3);
2212+
assert_eq!(vec.drain(..2).len(), 2);
2213+
assert_eq!(vec.into_iter().len(), 1);
21292214
}
21302215

21312216
#[test]

0 commit comments

Comments
 (0)