mirror of
https://github.com/openharmony/third_party_rust_tinyvec.git
synced 2026-07-21 01:35:22 -04:00
A bit of everything for iterators (#87)
* slight changes functions that use drain * bug in arrayvec iter * reverse iter for arrayvec * nth_back is stable since 1.37 * simpler drain for arrayvec * soveu forgot to add changed files * fmt + feature for rustc >= 1.40 * cosmetic changes * does the ci work now? * SHNAAAAAAAAATSEEEEEEEEL
This commit is contained in:
+55
-100
@@ -92,7 +92,7 @@ macro_rules! array_vec {
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct ArrayVec<A: Array> {
|
||||
len: usize,
|
||||
data: A,
|
||||
pub(crate) data: A,
|
||||
}
|
||||
|
||||
impl<A: Array> Deref for ArrayVec<A> {
|
||||
@@ -146,17 +146,12 @@ impl<A: Array> ArrayVec<A> {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn append(&mut self, other: &mut Self) {
|
||||
let new_len = self.len() + other.len();
|
||||
assert!(
|
||||
new_len <= A::CAPACITY,
|
||||
self.try_append(other).is_none(),
|
||||
"ArrayVec::append> total length {} exceeds capacity {}!",
|
||||
new_len,
|
||||
self.len() + other.len(),
|
||||
A::CAPACITY
|
||||
);
|
||||
|
||||
for item in other.drain(..) {
|
||||
self.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// Move all values from `other` into this vec.
|
||||
@@ -185,10 +180,13 @@ impl<A: Array> ArrayVec<A> {
|
||||
return Some(other);
|
||||
}
|
||||
|
||||
for item in other.drain(..) {
|
||||
let iter = other.iter_mut().map(take);
|
||||
for item in iter {
|
||||
self.push(item);
|
||||
}
|
||||
|
||||
other.set_len(0);
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -266,39 +264,11 @@ impl<A: Array> ArrayVec<A> {
|
||||
/// assert_eq!(av.as_slice(), &[]);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn drain<R: RangeBounds<usize>>(
|
||||
&mut self,
|
||||
range: R,
|
||||
) -> ArrayVecDrain<'_, A> {
|
||||
use core::ops::Bound;
|
||||
let start = match range.start_bound() {
|
||||
Bound::Included(x) => *x,
|
||||
Bound::Excluded(x) => x + 1,
|
||||
Bound::Unbounded => 0,
|
||||
};
|
||||
let end = match range.end_bound() {
|
||||
Bound::Included(x) => x + 1,
|
||||
Bound::Excluded(x) => *x,
|
||||
Bound::Unbounded => self.len,
|
||||
};
|
||||
assert!(
|
||||
start <= end,
|
||||
"ArrayVec::drain> Illegal range, {} to {}",
|
||||
start,
|
||||
end
|
||||
);
|
||||
assert!(
|
||||
end <= self.len,
|
||||
"ArrayVec::drain> Range ends at {} but length is only {}!",
|
||||
end,
|
||||
self.len
|
||||
);
|
||||
ArrayVecDrain {
|
||||
parent: self,
|
||||
target_start: start,
|
||||
target_index: start,
|
||||
target_end: end,
|
||||
}
|
||||
pub fn drain<R>(&mut self, range: R) -> ArrayVecDrain<'_, A::Item>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
ArrayVecDrain::new(self, range)
|
||||
}
|
||||
|
||||
/// Clone each element of the slice into this `ArrayVec`.
|
||||
@@ -526,11 +496,14 @@ impl<A: Array> ArrayVec<A> {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn try_push(&mut self, val: A::Item) -> Option<A::Item> {
|
||||
if self.len == A::CAPACITY {
|
||||
return Some(val);
|
||||
}
|
||||
debug_assert!(self.len <= A::CAPACITY);
|
||||
|
||||
self.data.as_slice_mut()[self.len] = val;
|
||||
let itemref = match self.data.as_slice_mut().get_mut(self.len) {
|
||||
None => return Some(val),
|
||||
Some(x) => x,
|
||||
};
|
||||
|
||||
*itemref = val;
|
||||
self.len += 1;
|
||||
return None;
|
||||
}
|
||||
@@ -940,44 +913,6 @@ impl<A: Array> ArrayVec<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draining iterator for [`ArrayVec`]
|
||||
///
|
||||
/// See [`ArrayVec::drain`](ArrayVec::drain)
|
||||
pub struct ArrayVecDrain<'p, A: Array> {
|
||||
parent: &'p mut ArrayVec<A>,
|
||||
target_start: usize,
|
||||
target_index: usize,
|
||||
target_end: usize,
|
||||
}
|
||||
impl<'p, A: Array> Iterator for ArrayVecDrain<'p, A> {
|
||||
type Item = A::Item;
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.target_index != self.target_end {
|
||||
let out = take(&mut self.parent[self.target_index]);
|
||||
self.target_index += 1;
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'p, A: Array> FusedIterator for ArrayVecDrain<'p, A> {}
|
||||
impl<'p, A: Array> Drop for ArrayVecDrain<'p, A> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
// Changed because it was moving `self`, it's also more clear and the std
|
||||
// does the same
|
||||
self.for_each(drop);
|
||||
// Implementation very similar to [`ArrayVec::remove`](ArrayVec::remove)
|
||||
let count = self.target_end - self.target_start;
|
||||
let targets: &mut [A::Item] =
|
||||
&mut self.parent.deref_mut()[self.target_start..];
|
||||
targets.rotate_left(count);
|
||||
self.parent.len -= count;
|
||||
}
|
||||
}
|
||||
|
||||
/// Splicing iterator for `ArrayVec`
|
||||
/// See [`ArrayVec::splice`](ArrayVec::<A>::splice)
|
||||
pub struct ArrayVecSplice<'p, A: Array, I: Iterator<Item = A::Item>> {
|
||||
@@ -1167,13 +1102,10 @@ impl<A: Array> Iterator for ArrayVecIterator<A> {
|
||||
type Item = A::Item;
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.base < self.len {
|
||||
let out = take(&mut self.data.as_slice_mut()[self.base]);
|
||||
self.base += 1;
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let slice = &mut self.data.as_slice_mut()[self.base..self.len];
|
||||
let itemref = slice.first_mut()?;
|
||||
self.base += 1;
|
||||
return Some(take(itemref));
|
||||
}
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
@@ -1187,18 +1119,39 @@ impl<A: Array> Iterator for ArrayVecIterator<A> {
|
||||
}
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
Some(take(&mut self.data.as_slice_mut()[self.len]))
|
||||
self.next_back()
|
||||
}
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<A::Item> {
|
||||
let i = self.base + (n - 1);
|
||||
if i < self.len {
|
||||
let out = take(&mut self.data.as_slice_mut()[i]);
|
||||
self.base = i + 1;
|
||||
Some(out)
|
||||
} else {
|
||||
None
|
||||
let slice = &mut self.data.as_slice_mut()[self.base..self.len];
|
||||
|
||||
if let Some(x) = slice.get_mut(n) {
|
||||
self.base += n + 1;
|
||||
return Some(take(x));
|
||||
}
|
||||
|
||||
self.base = self.len;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> DoubleEndedIterator for ArrayVecIterator<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
let slice = &mut self.data.as_slice_mut()[self.base..self.len];
|
||||
let item = slice.last_mut()?;
|
||||
self.len -= 1;
|
||||
return Some(take(item));
|
||||
}
|
||||
#[cfg(feature = "rustc_1_40")]
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let slice = &mut self.data.as_slice_mut()[self.base..self.len];
|
||||
let n = slice.len().checked_sub(n + 1)?;
|
||||
let item = &mut slice[n];
|
||||
self.len = n;
|
||||
|
||||
return Some(take(item));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1496,7 +1449,9 @@ impl<A: Array> ArrayVec<A> {
|
||||
pub fn drain_to_vec_and_reserve(&mut self, n: usize) -> Vec<A::Item> {
|
||||
let cap = n + self.len();
|
||||
let mut v = Vec::with_capacity(cap);
|
||||
v.extend(self.drain(..));
|
||||
let iter = self.iter_mut().map(take);
|
||||
v.extend(iter);
|
||||
self.set_len(0);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
use super::*;
|
||||
|
||||
use core::{
|
||||
ops::{Bound, RangeBounds},
|
||||
slice,
|
||||
};
|
||||
|
||||
/// Draining iterator for [`ArrayVec`]
|
||||
///
|
||||
/// See [`ArrayVec::drain`](ArrayVec::drain)
|
||||
pub struct ArrayVecDrain<'a, T: 'a + Default> {
|
||||
iter: slice::IterMut<'a, T>,
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Default> ArrayVecDrain<'a, T> {
|
||||
pub(crate) fn new<A, R>(arr: &'a mut ArrayVec<A>, range: R) -> Self
|
||||
where
|
||||
A: Array<Item = T>,
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
let start = match range.start_bound() {
|
||||
Bound::Unbounded => 0,
|
||||
Bound::Included(&n) => n,
|
||||
Bound::Excluded(&n) => n + 1,
|
||||
};
|
||||
let end = match range.end_bound() {
|
||||
Bound::Unbounded => arr.len(),
|
||||
Bound::Included(&n) => n + 1,
|
||||
Bound::Excluded(&n) => n,
|
||||
};
|
||||
|
||||
assert!(
|
||||
start <= end,
|
||||
"ArrayVec::drain> Illegal range, {} to {}",
|
||||
start,
|
||||
end
|
||||
);
|
||||
assert!(
|
||||
end <= arr.len(),
|
||||
"ArrayVec::drain> Range ends at {}, but length is only {}",
|
||||
end,
|
||||
arr.len()
|
||||
);
|
||||
|
||||
let len = end - start;
|
||||
let to_rotate = &mut arr[start..];
|
||||
to_rotate.rotate_left(len);
|
||||
|
||||
let oldlen = arr.len();
|
||||
let newlen = oldlen - len;
|
||||
arr.set_len(newlen);
|
||||
let slice = &mut arr.data.as_slice_mut()[newlen..oldlen];
|
||||
let iter = slice.iter_mut();
|
||||
Self { iter }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Default> DoubleEndedIterator for ArrayVecDrain<'a, T> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next_back().map(take)
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustc_1_40")]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.iter.nth_back(n).map(take)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Default> Iterator for ArrayVecDrain<'a, T> {
|
||||
type Item = T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(take)
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.iter.nth(n).map(take)
|
||||
}
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
self.iter.last().map(take)
|
||||
}
|
||||
fn for_each<F>(self, f: F)
|
||||
where
|
||||
F: FnMut(Self::Item),
|
||||
{
|
||||
self.iter.map(take).for_each(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Default> FusedIterator for ArrayVecDrain<'a, T> {}
|
||||
impl<'a, T: 'a + Default> ExactSizeIterator for ArrayVecDrain<'a, T> {}
|
||||
/* No need to impl Drop! */
|
||||
@@ -89,6 +89,9 @@ pub use arrayset::*;
|
||||
mod arrayvec;
|
||||
pub use arrayvec::*;
|
||||
|
||||
mod arrayvec_drain;
|
||||
pub use arrayvec_drain::*;
|
||||
|
||||
mod slicevec;
|
||||
pub use slicevec::*;
|
||||
|
||||
|
||||
+16
-4
@@ -280,14 +280,26 @@ impl<A: Array> TinyVec<A> {
|
||||
|
||||
impl<A: Array> TinyVec<A> {
|
||||
/// Move all values from `other` into this vec.
|
||||
#[cfg(feature = "rustc_1_40")]
|
||||
#[inline]
|
||||
pub fn append(&mut self, other: &mut Self) {
|
||||
self.reserve(other.len());
|
||||
let iter = other.drain(..);
|
||||
|
||||
match self {
|
||||
TinyVec::Heap(h) => h.extend(iter),
|
||||
TinyVec::Inline(a) => a.extend(iter),
|
||||
/* Doing append should be faster, because it is effectively a memcpy */
|
||||
match (self, other) {
|
||||
(TinyVec::Heap(sh), TinyVec::Heap(oh)) => sh.append(oh),
|
||||
(TinyVec::Inline(a), TinyVec::Heap(h)) => a.extend(h.drain(..)),
|
||||
(ref mut this, TinyVec::Inline(arr)) => this.extend(arr.drain(..)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Move all values from `other` into this vec.
|
||||
#[cfg(not(feature = "rustc_1_40"))]
|
||||
#[inline]
|
||||
pub fn append(&mut self, other: &mut Self) {
|
||||
match other {
|
||||
TinyVec::Inline(a) => self.extend(a.drain(..)),
|
||||
TinyVec::Heap(h) => self.extend(h.drain(..)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user