FIX: Add new_const() for const construction and revert new to old version

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`.
This commit is contained in:
bluss
2021-03-29 21:45:37 +02:00
parent 198a403194
commit b7f3aa9fce
4 changed files with 65 additions and 6 deletions
+20 -1
View File
@@ -59,8 +59,27 @@ impl<const CAP: usize> ArrayString<CAP>
/// assert_eq!(&string[..], "foo"); /// assert_eq!(&string[..], "foo");
/// assert_eq!(string.capacity(), 16); /// assert_eq!(string.capacity(), 16);
/// ``` /// ```
pub const fn new() -> ArrayString<CAP> { pub fn new() -> ArrayString<CAP> {
assert_capacity_limit!(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 } ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 }
} }
+21 -1
View File
@@ -77,8 +77,28 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
/// assert_eq!(&array[..], &[1, 2]); /// assert_eq!(&array[..], &[1, 2]);
/// assert_eq!(array.capacity(), 16); /// assert_eq!(array.capacity(), 16);
/// ``` /// ```
pub const fn new() -> ArrayVec<T, CAP> { pub fn new() -> ArrayVec<T, CAP> {
assert_capacity_limit!(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 } ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 }
} }
+10
View File
@@ -31,6 +31,16 @@ extern crate core as std;
pub(crate) type LenUint = u32; pub(crate) type LenUint = u32;
macro_rules! assert_capacity_limit { 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) => { ($cap:expr) => {
if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() { if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() {
if $cap > LenUint::MAX as usize { if $cap > LenUint::MAX as usize {
+14 -4
View File
@@ -718,19 +718,29 @@ fn allow_max_capacity_arrayvec_type() {
let _v: ArrayVec<(), {usize::MAX}>; let _v: ArrayVec<(), {usize::MAX}>;
} }
#[should_panic(expected="index out of bounds")] #[should_panic(expected="largest supported capacity")]
#[test] #[test]
fn deny_max_capacity_arrayvec_value() { fn deny_max_capacity_arrayvec_value() {
if mem::size_of::<usize>() <= mem::size_of::<u32>() { 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) // this type is allowed to be used (but can't be constructed)
let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); 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] #[test]
fn test_arrayvec_const_constructible() { 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; let mut var = OF_U8;
assert!(var.is_empty()); assert!(var.is_empty());
@@ -742,7 +752,7 @@ fn test_arrayvec_const_constructible() {
#[test] #[test]
fn test_arraystring_const_constructible() { fn test_arraystring_const_constructible() {
const AS: ArrayString<10> = ArrayString::new(); const AS: ArrayString<10> = ArrayString::new_const();
let mut var = AS; let mut var = AS;
assert!(var.is_empty()); assert!(var.is_empty());