Compare commits
10 Commits
aadc8df8c7
...
77041876ee
| Author | SHA1 | Date | |
|---|---|---|---|
| 77041876ee | |||
| 1bc606d8c8 | |||
| 29daea95b9 | |||
| 0ff49b9614 | |||
| 812c83a2b1 | |||
| 4ef0e89028 | |||
| 0aede877fe | |||
| 909c766e90 | |||
| f3732a0b4c | |||
| b629f5220a |
@@ -20,6 +20,8 @@ jobs:
|
||||
- rust: 1.51.0 # MSRV
|
||||
features: serde
|
||||
experimental: false
|
||||
# doctest of `ArrayVec::spare_capacity_mut` has MSRV 1.55
|
||||
test-args: --skip spare_capacity_mut
|
||||
- rust: 1.70.0
|
||||
features: serde
|
||||
experimental: false
|
||||
@@ -35,31 +37,54 @@ jobs:
|
||||
experimental: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: ${{ matrix.rust }}
|
||||
override: true
|
||||
- name: Pin versions for MSRV
|
||||
if: "${{ matrix.rust == '1.51.0' }}"
|
||||
run: |
|
||||
cargo update -p serde_test --precise 1.0.163
|
||||
cargo update -p serde --precise 1.0.69
|
||||
- name: Build
|
||||
run: |
|
||||
cargo build -v --no-default-features
|
||||
cargo build --verbose --features "${{ matrix.features }}"
|
||||
- name: Tests
|
||||
run: |
|
||||
cargo build --verbose --features "${{ matrix.features }}"
|
||||
cargo doc --verbose --features "${{ matrix.features }}" --no-deps
|
||||
cargo test --verbose --features "${{ matrix.features }}"
|
||||
cargo test --release --verbose --features "${{ matrix.features }}"
|
||||
cargo test --verbose --features "${{ matrix.features }}" -- ${{ matrix.test-args }}
|
||||
cargo test --release --verbose --features "${{ matrix.features }}" -- ${{ matrix.test-args }}
|
||||
- name: Test run benchmarks
|
||||
if: matrix.bench != ''
|
||||
run: cargo test -v --benches
|
||||
|
||||
nostd:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: false
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- rust: stable
|
||||
target: thumbv6m-none-eabi
|
||||
features: zeroize
|
||||
|
||||
name: nostd/${{ matrix.target }}/${{ matrix.rust }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
targets: ${{ matrix.target }}
|
||||
- name: Tests
|
||||
run: |
|
||||
cargo rustc "--target=${{ matrix.target }}" --no-default-features --features "${{ matrix.features }}"
|
||||
|
||||
|
||||
miri:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Miri
|
||||
run: |
|
||||
rustup toolchain install nightly --component miri
|
||||
|
||||
+11
-3
@@ -1,12 +1,20 @@
|
||||
Recent Changes (arrayvec)
|
||||
=========================
|
||||
|
||||
## 0.7.6
|
||||
|
||||
- Fix no-std build [#274](https://github.com/bluss/arrayvec/pull/274)
|
||||
|
||||
## 0.7.5
|
||||
|
||||
- Add `as_ptr` and `as_mut_ptr` to `ArrayString` by @YuhanLiin
|
||||
- Add borsh serialization support by @honzasp and @Fuuzetsu
|
||||
- Move length field before before data in ArrayVec and ArrayString by @JakkuSakura
|
||||
- Add `as_ptr` and `as_mut_ptr` to `ArrayString` [@YuhanLiin](https://github.com/YuhanLiin) [#260](https://github.com/bluss/arrayvec/pull/260)
|
||||
- Add borsh serialization support by @honzasp and @Fuuzetsu [#259](https://github.com/bluss/arrayvec/pull/259)
|
||||
- Move length field before before data in ArrayVec and ArrayString by @JakkuSakura [#255](https://github.com/bluss/arrayvec/pull/255)
|
||||
- Fix miri error for ZST case in extend by @bluss
|
||||
- implement AsRef<Path> for ArrayString by [@Zoybean](https://github.com/Zoybean) [#218](https://github.com/bluss/arrayvec/pull/218)
|
||||
- Fix typos in changelog by [@striezel](https://github.com/striezel) [#241](https://github.com/bluss/arrayvec/pull/241)
|
||||
- Add `as_slice`, `as_mut_slice` methods to `IntoIter` by [@clarfonthey](https://github.com/clarfonthey) [#224](https://github.com/bluss/arrayvec/pull/224)
|
||||
|
||||
|
||||
## 0.7.4
|
||||
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
version = "0.7.6"
|
||||
authors = ["bluss"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
@@ -48,6 +48,8 @@ harness = false
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
len_u16 = []
|
||||
len_u8 = []
|
||||
|
||||
[profile.bench]
|
||||
debug = true
|
||||
|
||||
+6
-3
@@ -5,6 +5,7 @@ use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(feature="std")]
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
@@ -26,8 +27,9 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
|
||||
/// The `ArrayString` is a string backed by a fixed size array. It keeps track
|
||||
/// of its length, and is parameterized by `CAP` for the maximum capacity.
|
||||
///
|
||||
/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger
|
||||
/// arrayvecs with larger capacity will panic.
|
||||
/// The length is stored in `u32` by default, and can be changed to `u16` or `u8`
|
||||
/// by `len_u16` or `len_u8` feature. Attempting to create arrayvecs with larger
|
||||
/// capacity will panic.
|
||||
///
|
||||
/// The string is a contiguous value that you can store directly on the stack
|
||||
/// if needed.
|
||||
@@ -75,7 +77,7 @@ impl<const CAP: usize> ArrayString<CAP>
|
||||
/// ```
|
||||
/// use arrayvec::ArrayString;
|
||||
///
|
||||
/// static ARRAY: ArrayString<1024> = ArrayString::new_const();
|
||||
/// static ARRAY: ArrayString<255> = ArrayString::new_const();
|
||||
/// ```
|
||||
pub const fn new_const() -> ArrayString<CAP> {
|
||||
assert_capacity_limit_const!(CAP);
|
||||
@@ -502,6 +504,7 @@ impl<const CAP: usize> fmt::Debug for ArrayString<CAP>
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
impl<const CAP: usize> AsRef<Path> for ArrayString<CAP> {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.as_str().as_ref()
|
||||
|
||||
+46
-5
@@ -31,8 +31,9 @@ use crate::utils::MakeMaybeUninit;
|
||||
/// the number of initialized elements. The `ArrayVec<T, CAP>` is parameterized
|
||||
/// by `T` for the element type and `CAP` for the maximum capacity.
|
||||
///
|
||||
/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger
|
||||
/// arrayvecs with larger capacity will panic.
|
||||
/// The length is stored in `u32` by default, and can be changed to `u16` or `u8`
|
||||
/// by `len_u16` or `len_u8` feature. Attempting to create arrayvecs with larger
|
||||
/// capacity will panic.
|
||||
///
|
||||
/// The vector is a contiguous value (storing the elements inline) that you can store directly on
|
||||
/// the stack if needed.
|
||||
@@ -94,7 +95,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
|
||||
/// ```
|
||||
/// use arrayvec::ArrayVec;
|
||||
///
|
||||
/// static ARRAY: ArrayVec<u8, 1024> = ArrayVec::new_const();
|
||||
/// static ARRAY: ArrayVec<u8, 255> = ArrayVec::new_const();
|
||||
/// ```
|
||||
pub const fn new_const() -> ArrayVec<T, CAP> {
|
||||
assert_capacity_limit_const!(CAP);
|
||||
@@ -535,6 +536,41 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
|
||||
drop(g);
|
||||
}
|
||||
|
||||
/// Returns the remaining spare capacity of the vector as a slice of
|
||||
/// `MaybeUninit<T>`.
|
||||
///
|
||||
/// The returned slice can be used to fill the vector with data (e.g. by
|
||||
/// reading from a file) before marking the data as initialized using the
|
||||
/// [`set_len`] method.
|
||||
///
|
||||
/// [`set_len`]: ArrayVec::set_len
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use arrayvec::ArrayVec;
|
||||
///
|
||||
/// // Allocate vector big enough for 10 elements.
|
||||
/// let mut v: ArrayVec<i32, 10> = ArrayVec::new();
|
||||
///
|
||||
/// // Fill in the first 3 elements.
|
||||
/// let uninit = v.spare_capacity_mut();
|
||||
/// uninit[0].write(0);
|
||||
/// uninit[1].write(1);
|
||||
/// uninit[2].write(2);
|
||||
///
|
||||
/// // Mark the first 3 elements of the vector as being initialized.
|
||||
/// unsafe {
|
||||
/// v.set_len(3);
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(&v[..], &[0, 1, 2]);
|
||||
/// ```
|
||||
pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
|
||||
let len = self.len();
|
||||
&mut self.xs[len..]
|
||||
}
|
||||
|
||||
/// Set the vector’s length without dropping or moving out elements
|
||||
///
|
||||
/// This method is `unsafe` because it changes the notion of the
|
||||
@@ -602,7 +638,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
|
||||
/// assert_eq!(&v1[..], &[3]);
|
||||
/// assert_eq!(&v2[..], &[1, 2]);
|
||||
/// ```
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP>
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, CAP>
|
||||
where R: RangeBounds<usize>
|
||||
{
|
||||
// Memory safety
|
||||
@@ -629,7 +665,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
|
||||
self.drain_range(start, end)
|
||||
}
|
||||
|
||||
fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP>
|
||||
fn drain_range(&mut self, start: usize, end: usize) -> Drain<'_, T, CAP>
|
||||
{
|
||||
let len = self.len();
|
||||
|
||||
@@ -1102,6 +1138,11 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
|
||||
debug_assert_ne!(ptr, end_ptr);
|
||||
if mem::size_of::<T>() != 0 {
|
||||
ptr.write(elt);
|
||||
} else {
|
||||
// The ZST element has logically been moved into the vector.
|
||||
// There is no memory to write, but dropping `elt` here would
|
||||
// drop it once now and once again when the vector is dropped.
|
||||
mem::forget(elt);
|
||||
}
|
||||
ptr = raw_ptr_add(ptr, 1);
|
||||
guard.data += 1;
|
||||
|
||||
+17
-2
@@ -7,6 +7,14 @@
|
||||
//! - Optional, enabled by default
|
||||
//! - Use libstd; disable to use `no_std` instead.
|
||||
//!
|
||||
//! - `len_u16`
|
||||
//! - Optional.
|
||||
//! - Use `u16` as length type.
|
||||
//!
|
||||
//! - `len_u8`
|
||||
//! - Optional.
|
||||
//! - Use `u8` as length type.
|
||||
//!
|
||||
//! - `serde`
|
||||
//! - Optional
|
||||
//! - Enable serialization for ArrayVec and ArrayString using serde 1.x
|
||||
@@ -28,13 +36,20 @@ extern crate serde;
|
||||
#[cfg(not(feature="std"))]
|
||||
extern crate core as std;
|
||||
|
||||
#[cfg(all(not(feature="len_u8"), not(feature="len_u16")))]
|
||||
pub(crate) type LenUint = u32;
|
||||
|
||||
#[cfg(feature="len_u16")]
|
||||
pub(crate) type LenUint = u16;
|
||||
|
||||
#[cfg(feature="len_u8")]
|
||||
pub(crate) type LenUint = u8;
|
||||
|
||||
macro_rules! assert_capacity_limit {
|
||||
($cap:expr) => {
|
||||
if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() {
|
||||
if $cap > LenUint::MAX as usize {
|
||||
panic!("ArrayVec: largest supported capacity is u32::MAX")
|
||||
panic!("ArrayVec: largest supported capacity is {}", LenUint::MAX)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +59,7 @@ macro_rules! assert_capacity_limit_const {
|
||||
($cap:expr) => {
|
||||
if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() {
|
||||
if $cap > LenUint::MAX as usize {
|
||||
[/*ArrayVec: largest supported capacity is u32::MAX*/][$cap]
|
||||
[/*ArrayVec: largest supported capacity is LenUint::MAX*/][$cap]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
-7
@@ -75,6 +75,7 @@ fn test_try_from_slice_error() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature="len_u16")]
|
||||
fn test_u16_index() {
|
||||
const N: usize = 4096;
|
||||
let mut vec: ArrayVec<_, N> = ArrayVec::new();
|
||||
@@ -680,8 +681,9 @@ fn test_pop_at() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_pointer_width = "16"))]
|
||||
fn test_sizes() {
|
||||
let v = ArrayVec::from([0u8; 1 << 16]);
|
||||
let v = ArrayVec::from([0u8; 255]);
|
||||
assert_eq!(vec![0u8; v.len()], &v[..]);
|
||||
}
|
||||
|
||||
@@ -715,6 +717,32 @@ fn test_extend_zst() {
|
||||
assert_eq!(array.len(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extend_zst_with_drop_is_not_dropped_twice_via_safe_api() {
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
struct ZstWithSafeDrop;
|
||||
|
||||
impl Drop for ZstWithSafeDrop {
|
||||
fn drop(&mut self) {
|
||||
let previous = DROP_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||
// Extending with a single ZST moves one logical value into the ArrayVec.
|
||||
// Its Drop implementation must run exactly once, when the ArrayVec drops.
|
||||
if previous != 0 {
|
||||
panic!("ZST value dropped more than once");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DROP_COUNT.store(0, Ordering::SeqCst);
|
||||
|
||||
let mut vec = ArrayVec::<ZstWithSafeDrop, 1>::new();
|
||||
vec.extend(std::iter::once(ZstWithSafeDrop));
|
||||
drop(vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_argument() {
|
||||
use core::convert::TryFrom;
|
||||
@@ -729,21 +757,17 @@ fn allow_max_capacity_arrayvec_type() {
|
||||
}
|
||||
|
||||
#[should_panic(expected="largest supported capacity")]
|
||||
#[cfg(not(target_pointer_width = "16"))]
|
||||
#[test]
|
||||
fn deny_max_capacity_arrayvec_value() {
|
||||
if mem::size_of::<usize>() <= mem::size_of::<u32>() {
|
||||
panic!("This test does not work on this platform. 'largest supported capacity'");
|
||||
}
|
||||
// this type is allowed to be used (but can't be constructed)
|
||||
let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new();
|
||||
}
|
||||
|
||||
#[should_panic(expected="index out of bounds")]
|
||||
#[cfg(not(target_pointer_width = "16"))]
|
||||
#[test]
|
||||
fn deny_max_capacity_arrayvec_value_const() {
|
||||
if mem::size_of::<usize>() <= mem::size_of::<u32>() {
|
||||
panic!("This test does not work on this platform. 'index out of bounds'");
|
||||
}
|
||||
// this type is allowed to be used (but can't be constructed)
|
||||
let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user