mirror of
https://github.com/rust-embedded/heapless.git
synced 2025-10-02 23:04:40 +00:00
Merge #38
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:
commit
495cace695
127
src/vec.rs
127
src/vec.rs
@ -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>
|
impl<A, B, N1, N2> PartialEq<Vec<B, N2>> for Vec<A, N1>
|
||||||
where
|
where
|
||||||
N1: ArrayLength<A>,
|
N1: ArrayLength<A>,
|
||||||
@ -433,8 +493,8 @@ mod tests {
|
|||||||
use consts::*;
|
use consts::*;
|
||||||
use Vec;
|
use Vec;
|
||||||
|
|
||||||
#[test]
|
macro_rules! droppable {
|
||||||
fn drop() {
|
() => (
|
||||||
struct Droppable;
|
struct Droppable;
|
||||||
impl Droppable {
|
impl Droppable {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
@ -453,6 +513,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static mut COUNT: i32 = 0;
|
static mut COUNT: i32 = 0;
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn drop() {
|
||||||
|
|
||||||
|
droppable!();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut v: Vec<Droppable, U2> = Vec::new();
|
let mut v: Vec<Droppable, U2> = Vec::new();
|
||||||
@ -533,6 +600,62 @@ mod tests {
|
|||||||
assert_eq!(items.next(), None);
|
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]
|
#[test]
|
||||||
fn push_and_pop() {
|
fn push_and_pop() {
|
||||||
let mut v: Vec<i32, U4> = Vec::new();
|
let mut v: Vec<i32, U4> = Vec::new();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user