mirror of
https://github.com/openharmony/third_party_rust_tinyvec.git
synced 2026-07-18 12:25:35 -04:00
Add the SliceVec type (#68)
* start of slicevec * remove todo! because it's not in 1.36 * Update Cargo.toml * slice vec into iterator * slicevec drain * complete last unimplemented * remove the extra default feature * spelling * Update src/slicevec.rs Co-Authored-By: Joshua Nelson <joshua@yottadb.com> * docs clarification. Co-authored-by: Joshua Nelson <joshua@yottadb.com>
This commit is contained in:
+9
-4
@@ -15,11 +15,11 @@ repository = "https://github.com/Lokathor/tinyvec"
|
||||
[features]
|
||||
default = []
|
||||
|
||||
# Provide things that utilize the `alloc` crate.
|
||||
# Provide things that utilize the `alloc` crate, namely `TinyVec`.
|
||||
alloc = []
|
||||
|
||||
# (not part of Vec!) Extra methods to let you grab the slice of memory after the
|
||||
# "active" portion of an `ArrayVec`.
|
||||
# "active" portion of an `ArrayVec` or `SliceVec`.
|
||||
grab_spare_slice = []
|
||||
|
||||
# allow use of nightly feature `slice_partition_dedup`,
|
||||
@@ -30,8 +30,10 @@ nightly_slice_partition_dedup = []
|
||||
# use const generics for arrays
|
||||
nightly_const_generics = []
|
||||
|
||||
# NOT considered part of the crate's SemVer!!!
|
||||
# This experimental feature adds `core::fmt::Write` to ArrayVec.
|
||||
# EXPERIMENTAL: Not part of SemVer. It adds `core::fmt::Write` to `ArrayVec`
|
||||
# and `SliceVec`. It works on Stable Rust, but Vec normally supports the
|
||||
# `std::io::Write` trait instead of `core::fmt::Write`, so we're keeping it as
|
||||
# an experimental impl only for now.
|
||||
experimental_write_impl = []
|
||||
|
||||
[badges]
|
||||
@@ -41,6 +43,9 @@ travis-ci = { repository = "Lokathor/tinyvec" }
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
||||
[profile.test]
|
||||
opt-level = 3
|
||||
|
||||
[workspace]
|
||||
members = ["fuzz"]
|
||||
|
||||
|
||||
+70
-67
@@ -287,22 +287,62 @@ impl<A: Array> ArrayVec<A> {
|
||||
self.set_len(new_len);
|
||||
}
|
||||
|
||||
/// Fill the vector until its capacity has been reached.
|
||||
///
|
||||
/// Successively fills unused space in the spare slice of the vector with
|
||||
/// elements from the iterator. It then returns the remaining iterator
|
||||
/// without exhausting it. This also allows appending the head of an
|
||||
/// infinite iterator.
|
||||
///
|
||||
/// This is an alternative to `Extend::extend` method for cases where the
|
||||
/// length of the iterator can not be checked. Since this vector can not
|
||||
/// reallocate to increase its capacity, it is unclear what to do with
|
||||
/// remaining elements in the iterator and the iterator itself. The
|
||||
/// interface also provides no way to communicate this to the caller.
|
||||
///
|
||||
/// ## Panics
|
||||
/// * If the `next` method of the provided iterator panics.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use tinyvec::*;
|
||||
/// let mut av = array_vec!([i32; 4]);
|
||||
/// let mut to_inf = av.fill(0..);
|
||||
/// assert_eq!(&av[..], [0, 1, 2, 3]);
|
||||
/// assert_eq!(to_inf.next(), Some(4));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn fill<I: IntoIterator<Item = A::Item>>(
|
||||
&mut self,
|
||||
iter: I,
|
||||
) -> I::IntoIter {
|
||||
let mut iter = iter.into_iter();
|
||||
for element in iter.by_ref().take(self.capacity() - self.len()) {
|
||||
self.push(element);
|
||||
}
|
||||
iter
|
||||
}
|
||||
|
||||
/// Wraps up an array and uses the given length as the initial length.
|
||||
///
|
||||
/// If you want to simply use the full array, use `from` instead.
|
||||
///
|
||||
/// ## Panics
|
||||
///
|
||||
/// * The length specified must be less than or equal to the capacity of the array.
|
||||
/// * The length specified must be less than or equal to the capacity of the
|
||||
/// array.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[allow(clippy::match_wild_err_arm)]
|
||||
pub fn from_array_len(data: A, len: usize) -> Self {
|
||||
match Self::try_from_array_len(data, len) {
|
||||
Ok(out) => out,
|
||||
Err(_) => {
|
||||
panic!("ArrayVec::from_array_len> length {} exceeds capacity {}!", len, A::CAPACITY)
|
||||
}
|
||||
Err(_) => panic!(
|
||||
"ArrayVec::from_array_len> length {} exceeds capacity {}!",
|
||||
len,
|
||||
A::CAPACITY
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +350,7 @@ impl<A: Array> ArrayVec<A> {
|
||||
/// index.
|
||||
///
|
||||
/// ## Panics
|
||||
/// * If `index` > `len` or
|
||||
/// * If `index` > `len`
|
||||
/// * If the capacity is exhausted
|
||||
///
|
||||
/// ## Example
|
||||
@@ -427,16 +467,14 @@ impl<A: Array> ArrayVec<A> {
|
||||
#[inline]
|
||||
pub fn remove(&mut self, index: usize) -> A::Item {
|
||||
let targets: &mut [A::Item] = &mut self.deref_mut()[index..];
|
||||
let item = replace(&mut targets[0], A::Item::default());
|
||||
let item = take(&mut targets[0]);
|
||||
targets.rotate_left(1);
|
||||
self.len -= 1;
|
||||
item
|
||||
}
|
||||
|
||||
/// Resize the vec to the new length.
|
||||
///
|
||||
/// If it needs to be longer, it's filled with clones of the provided value.
|
||||
/// If it needs to be shorter, it's truncated.
|
||||
/// As [`resize_with`](ArrayVec::resize_with)
|
||||
/// and it clones the value as the closure.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
@@ -456,16 +494,7 @@ impl<A: Array> ArrayVec<A> {
|
||||
where
|
||||
A::Item: Clone,
|
||||
{
|
||||
match new_len.checked_sub(self.len) {
|
||||
None => self.truncate(new_len),
|
||||
Some(0) => (),
|
||||
Some(new_elements) => {
|
||||
for _ in 1..new_elements {
|
||||
self.push(new_val.clone());
|
||||
}
|
||||
self.push(new_val);
|
||||
}
|
||||
}
|
||||
self.resize_with(new_len, || new_val.clone())
|
||||
}
|
||||
|
||||
/// Resize the vec to the new length.
|
||||
@@ -484,7 +513,10 @@ impl<A: Array> ArrayVec<A> {
|
||||
///
|
||||
/// let mut av = array_vec!([i32; 10]);
|
||||
/// let mut p = 1;
|
||||
/// av.resize_with(4, || { p *= 2; p });
|
||||
/// av.resize_with(4, || {
|
||||
/// p *= 2;
|
||||
/// p
|
||||
/// });
|
||||
/// assert_eq!(&av[..], [2, 4, 8, 16]);
|
||||
/// ```
|
||||
#[inline]
|
||||
@@ -567,49 +599,16 @@ impl<A: Array> ArrayVec<A> {
|
||||
// just let some other call later on trigger a panic on accident when the
|
||||
// length is wrong. However, it's a lot easier to catch bugs when things
|
||||
// are more "fail-fast".
|
||||
panic!("ArrayVec: set_len overflow!")
|
||||
panic!(
|
||||
"ArrayVec::set_len> new length {} exceeds capacity {}",
|
||||
new_len,
|
||||
A::CAPACITY
|
||||
)
|
||||
} else {
|
||||
self.len = new_len;
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill the vector until its capacity has been reached.
|
||||
///
|
||||
/// Successively fills unused space in the spare slice of the vector with
|
||||
/// elements from the iterator. It then returns the remaining iterator
|
||||
/// without exhausting it. This also allows appending the head of an
|
||||
/// infinite iterator.
|
||||
///
|
||||
/// This is an alternative to `Extend::extend` method for cases where the
|
||||
/// length of the iterator can not be checked. Since this vector can not
|
||||
/// reallocate to increase its capacity, it is unclear what to do with
|
||||
/// remaining elements in the iterator and the iterator itself. The
|
||||
/// interface also provides no way to communicate this to the caller.
|
||||
///
|
||||
/// ## Panics
|
||||
/// * If the `next` method of the provided iterator panics.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use tinyvec::*;
|
||||
/// let mut av = array_vec!([i32; 4]);
|
||||
/// let mut to_inf = av.fill(0..);
|
||||
/// assert_eq!(&av[..], [0, 1, 2, 3]);
|
||||
/// assert_eq!(to_inf.next(), Some(4));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn fill<I: IntoIterator<Item = A::Item>>(
|
||||
&mut self,
|
||||
iter: I,
|
||||
) -> I::IntoIter {
|
||||
let mut iter = iter.into_iter();
|
||||
for element in iter.by_ref().take(self.capacity() - self.len()) {
|
||||
self.push(element);
|
||||
}
|
||||
iter
|
||||
}
|
||||
|
||||
/// Splits the collection at the point given.
|
||||
///
|
||||
/// * `[0, at)` stays in this vec
|
||||
@@ -786,7 +785,7 @@ impl<A: Array> ArrayVec<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draining iterator for `ArrayVecDrain`
|
||||
/// Draining iterator for [`ArrayVec`]
|
||||
///
|
||||
/// See [`ArrayVec::drain`](ArrayVec::drain)
|
||||
pub struct ArrayVecDrain<'p, A: Array> {
|
||||
@@ -808,15 +807,17 @@ impl<'p, A: Array> Iterator for ArrayVecDrain<'p, A> {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'p, A: Array> FusedIterator for ArrayVecDrain<'p, A> { }
|
||||
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
|
||||
// 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..];
|
||||
let targets: &mut [A::Item] =
|
||||
&mut self.parent.deref_mut()[self.target_start..];
|
||||
targets.rotate_left(count);
|
||||
self.parent.len -= count;
|
||||
}
|
||||
@@ -902,7 +903,7 @@ impl<A: Array> ArrayVecIterator<A> {
|
||||
&self.data.as_slice()[self.base..self.len]
|
||||
}
|
||||
}
|
||||
impl<A: Array> FusedIterator for ArrayVecIterator<A> { }
|
||||
impl<A: Array> FusedIterator for ArrayVecIterator<A> {}
|
||||
impl<A: Array> Iterator for ArrayVecIterator<A> {
|
||||
type Item = A::Item;
|
||||
#[inline]
|
||||
@@ -942,7 +943,10 @@ impl<A: Array> Iterator for ArrayVecIterator<A> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> Debug for ArrayVecIterator<A> where A::Item: Debug {
|
||||
impl<A: Array> Debug for ArrayVecIterator<A>
|
||||
where
|
||||
A::Item: Debug,
|
||||
{
|
||||
#[allow(clippy::missing_inline_in_public_items)]
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_tuple("ArrayVecIterator").field(&self.as_slice()).finish()
|
||||
@@ -1045,8 +1049,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "experimental_write_impl")]
|
||||
impl<A: Array<Item=u8>> core::fmt::Write for ArrayVec<A>
|
||||
{
|
||||
impl<A: Array<Item = u8>> core::fmt::Write for ArrayVec<A> {
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
let my_len = self.len();
|
||||
let str_len = s.as_bytes().len();
|
||||
|
||||
+15
-5
@@ -28,6 +28,11 @@
|
||||
//! * [`ArrayVec`](ArrayVec) is an array-backed vec-like structure with a fixed
|
||||
//! capacity. If you try to grow the length past the array's capacity it will
|
||||
//! error or panic (depending on the method used).
|
||||
//! * [`SliceVec`](SliceVec) is similar, but instead of the vec having an owned
|
||||
//! array, it holds onto a unique borrow of a slice. This means that it's far
|
||||
//! cheaper to pass around (since you don't move the whole array), but it can
|
||||
//! be trickier to thread a lifetime marker everywhere through all your
|
||||
//! function signatures.
|
||||
//! * (`alloc` feature) [`TinyVec`](TinyVec) is an enum that's either an
|
||||
//! "Inline" `ArrayVec` or a "Heap" `Vec`. If it's Inline and you try to grow
|
||||
//! the `ArrayVec` beyond its array capacity it will quietly transition into
|
||||
@@ -42,22 +47,24 @@
|
||||
//! `serde` compatibility).
|
||||
//! 3) The intended API is that, _as much as possible_, these types are
|
||||
//! essentially a "drop-in" replacement for the standard [`Vec`](Vec::<T>)
|
||||
//! type.
|
||||
//! type. Because of the "no `unsafe`" rule this can't be done perfectly.
|
||||
//! * Stable `Vec` methods that the vecs here also have should be the same
|
||||
//! general signature.
|
||||
//! * Unstable `Vec` methods are sometimes provided via a crate feature, but
|
||||
//! if so they also require a Nightly compiler.
|
||||
//! * Some methods are provided that _are not_ part of the `Vec` type, such
|
||||
//! as additional constructor methods. In this case, the names are rather
|
||||
//! long and whimsical in the hopes that they don't clash with any
|
||||
//! possible future methods of `Vec`.
|
||||
//! long and whimsical in the hopes that they don't clash with any possible
|
||||
//! future methods of `Vec`.
|
||||
//! * If, in the future, `Vec` stabilizes a method that clashes with an
|
||||
//! existing extra method here then we'll simply be forced to release a
|
||||
//! 2.y.z version. Not the end of the world.
|
||||
//! * Some methods of `Vec` are simply inappropriate and will not be
|
||||
//! implemented here. For example, `ArrayVec` cannot possibly implement
|
||||
//! [`from_raw_parts`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.from_raw_parts).
|
||||
//! implemented here. For example, this crate cannot possibly implement
|
||||
//! [`from_raw_parts`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.from_raw_parts)
|
||||
//! because it cannot call `unsafe` methods.
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use core::{
|
||||
borrow::{Borrow, BorrowMut},
|
||||
cmp::PartialEq,
|
||||
@@ -84,6 +91,9 @@ pub use array::*;
|
||||
mod arrayvec;
|
||||
pub use arrayvec::*;
|
||||
|
||||
mod slicevec;
|
||||
pub use slicevec::*;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
mod tinyvec;
|
||||
#[cfg(feature = "alloc")]
|
||||
|
||||
+1025
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
#![cfg(feature = "alloc")]
|
||||
|
||||
#![allow(bad_style)]
|
||||
#![allow(clippy::redundant_clone)]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user