Skip to content

Commit

Permalink
FIX: Add new_const() for const construction and revert new to old ver…
Browse files Browse the repository at this point in the history
…sion

The new() function is significantly faster, it optimizes better at the
moment/in current rust. For this reason, provide a const fn constructor,
but not as the default `new`.
  • Loading branch information
bluss committed Mar 29, 2021
1 parent 198a403 commit b7f3aa9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 6 deletions.
21 changes: 20 additions & 1 deletion src/array_string.rs
Expand Up @@ -59,8 +59,27 @@ impl<const CAP: usize> ArrayString<CAP>
/// assert_eq!(&string[..], "foo");
/// assert_eq!(string.capacity(), 16);
/// ```
pub const fn new() -> ArrayString<CAP> {
pub fn new() -> ArrayString<CAP> {
assert_capacity_limit!(CAP);
unsafe {
ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 }
}
}

/// Create a new empty `ArrayString` (const fn).
///
/// Capacity is inferred from the type parameter.
///
/// ```
/// use arrayvec::ArrayString;
///
/// let mut string = ArrayString::<16>::new();
/// string.push_str("foo");
/// assert_eq!(&string[..], "foo");
/// assert_eq!(string.capacity(), 16);
/// ```
pub const fn new_const() -> ArrayString<CAP> {
assert_capacity_limit_const!(CAP);
ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 }
}

Expand Down
22 changes: 21 additions & 1 deletion src/arrayvec.rs
Expand Up @@ -77,8 +77,28 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
/// assert_eq!(&array[..], &[1, 2]);
/// assert_eq!(array.capacity(), 16);
/// ```
pub const fn new() -> ArrayVec<T, CAP> {
pub fn new() -> ArrayVec<T, CAP> {
assert_capacity_limit!(CAP);
unsafe {
ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 }
}
}

/// Create a new empty `ArrayVec` (const fn).
///
/// The maximum capacity is given by the generic parameter `CAP`.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::<_, 16>::new();
/// array.push(1);
/// array.push(2);
/// assert_eq!(&array[..], &[1, 2]);
/// assert_eq!(array.capacity(), 16);
/// ```
pub const fn new_const() -> ArrayVec<T, CAP> {
assert_capacity_limit_const!(CAP);
ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 }
}

Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Expand Up @@ -31,6 +31,16 @@ extern crate core as std;
pub(crate) type LenUint = u32;

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")
}
}
}
}

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 {
Expand Down
18 changes: 14 additions & 4 deletions tests/tests.rs
Expand Up @@ -718,19 +718,29 @@ fn allow_max_capacity_arrayvec_type() {
let _v: ArrayVec<(), {usize::MAX}>;
}

#[should_panic(expected="index out of bounds")]
#[should_panic(expected="largest supported capacity")]
#[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. 'index out of bounds'");
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")]
#[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();
}

#[test]
fn test_arrayvec_const_constructible() {
const OF_U8: ArrayVec<Vec<u8>, 10> = ArrayVec::new();
const OF_U8: ArrayVec<Vec<u8>, 10> = ArrayVec::new_const();

let mut var = OF_U8;
assert!(var.is_empty());
Expand All @@ -742,7 +752,7 @@ fn test_arrayvec_const_constructible() {

#[test]
fn test_arraystring_const_constructible() {
const AS: ArrayString<10> = ArrayString::new();
const AS: ArrayString<10> = ArrayString::new_const();

let mut var = AS;
assert!(var.is_empty());
Expand Down

0 comments on commit b7f3aa9

Please sign in to comment.