38: Implement IntoIter for Vec r=japaric a=XOSplicer

~~This implementation uses vec::reverse and vec::pop to move the content of the vector out of it.~~

It might give more performance to avoid the `reverse` and read each element individually. In the end  the unmoved items need to be dropped.



Co-authored-by: Felix <stegmaier.felix@gmail.com>
Co-authored-by: Felix Stegmaier <stegmaier.felix@gmail.com>
This commit is contained in:
bors[bot] 2018-05-14 16:32:21 +00:00
commit 495cace695

View File

@ -310,6 +310,66 @@ where
}
}
/// An iterator that moves out of an [`Vec`][`Vec`].
///
/// This struct is created by calling the `into_iter` method on [`Vec`][`Vec`].
///
/// [`Vec`]: (https://doc.rust-lang.org/std/vec/struct.Vec.html)
///
pub struct IntoIter<T, N>
where
N: ArrayLength<T>,
{
vec: Vec<T, N>,
next: usize,
}
impl <T, N> Iterator for IntoIter<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.next < self.vec.len() {
let buffer = self.vec.buffer.as_slice();
let item = unsafe {ptr::read(buffer.get_unchecked(self.next))};
self.next += 1;
Some(item)
} else {
None
}
}
}
impl <T, N> Drop for IntoIter<T, N>
where
N: ArrayLength<T>,
{
fn drop(&mut self) {
unsafe {
// Drop all the elements that have not been moved out of vec
ptr::drop_in_place(&mut self.vec[self.next..]);
// Prevent dropping of other elements
self.vec.len = 0;
}
}
}
impl <T, N> IntoIterator for Vec<T, N>
where
N: ArrayLength<T>,
{
type Item = T;
type IntoIter = IntoIter<T, N>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
vec: self,
next: 0,
}
}
}
impl<A, B, N1, N2> PartialEq<Vec<B, N2>> for Vec<A, N1>
where
N1: ArrayLength<A>,
@ -433,26 +493,33 @@ mod tests {
use consts::*;
use Vec;
macro_rules! droppable {
() => (
struct Droppable;
impl Droppable {
fn new() -> Self {
unsafe {
COUNT += 1;
}
Droppable
}
}
impl Drop for Droppable {
fn drop(&mut self) {
unsafe {
COUNT -= 1;
}
}
}
static mut COUNT: i32 = 0;
)
}
#[test]
fn drop() {
struct Droppable;
impl Droppable {
fn new() -> Self {
unsafe {
COUNT += 1;
}
Droppable
}
}
impl Drop for Droppable {
fn drop(&mut self) {
unsafe {
COUNT -= 1;
}
}
}
static mut COUNT: i32 = 0;
droppable!();
{
let mut v: Vec<Droppable, U2> = Vec::new();
@ -533,6 +600,62 @@ mod tests {
assert_eq!(items.next(), None);
}
#[test]
fn iter_move() {
let mut v: Vec<i32, U4> = Vec::new();
v.push(0).unwrap();
v.push(1).unwrap();
v.push(2).unwrap();
v.push(3).unwrap();
let mut items = v.into_iter();
assert_eq!(items.next(), Some(0));
assert_eq!(items.next(), Some(1));
assert_eq!(items.next(), Some(2));
assert_eq!(items.next(), Some(3));
assert_eq!(items.next(), None);
}
#[test]
fn iter_move_drop() {
droppable!();
{
let mut vec: Vec<Droppable, U2> = Vec::new();
vec.push(Droppable::new()).ok().unwrap();
vec.push(Droppable::new()).ok().unwrap();
let mut items = vec.into_iter();
// Move all
let _ = items.next();
let _ = items.next();
}
assert_eq!(unsafe { COUNT }, 0);
{
let mut vec: Vec<Droppable, U2> = Vec::new();
vec.push(Droppable::new()).ok().unwrap();
vec.push(Droppable::new()).ok().unwrap();
let _items = vec.into_iter();
// Move none
}
assert_eq!(unsafe { COUNT }, 0);
{
let mut vec: Vec<Droppable, U2> = Vec::new();
vec.push(Droppable::new()).ok().unwrap();
vec.push(Droppable::new()).ok().unwrap();
let mut items = vec.into_iter();
let _ = items.next(); // Move partly
}
assert_eq!(unsafe { COUNT }, 0);
}
#[test]
fn push_and_pop() {
let mut v: Vec<i32, U4> = Vec::new();