diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0aeb6e6..ca278e84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,15 +13,14 @@ env: jobs: tests: runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: include: - - rust: 1.36.0 # MSRV + - rust: 1.51.0 # MSRV features: serde - rust: stable - features: serde - - rust: stable - features: array-sizes-33-128 array-sizes-129-255 + features: - rust: beta features: serde - rust: nightly diff --git a/Cargo.toml b/Cargo.toml index d1303887..3ebe7a9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,9 +39,6 @@ default = ["std"] std = [] unstable-const-fn = [] -array-sizes-33-128 = [] -array-sizes-129-255 = [] - [profile.bench] debug = true [profile.release] diff --git a/benches/arraystring.rs b/benches/arraystring.rs index 9cff5875..5b986fa2 100644 --- a/benches/arraystring.rs +++ b/benches/arraystring.rs @@ -7,7 +7,7 @@ use arrayvec::ArrayString; use bencher::Bencher; fn try_push_c(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while v.try_push('c').is_ok() { @@ -18,7 +18,7 @@ fn try_push_c(b: &mut Bencher) { } fn try_push_alpha(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while v.try_push('α').is_ok() { @@ -30,7 +30,7 @@ fn try_push_alpha(b: &mut Bencher) { // Yes, pushing a string char-by-char is slow. Use .push_str. fn try_push_string(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); let input = "abcαβγ“”"; b.iter(|| { v.clear(); @@ -45,7 +45,7 @@ fn try_push_string(b: &mut Bencher) { } fn push_c(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while !v.is_full() { @@ -57,7 +57,7 @@ fn push_c(b: &mut Bencher) { } fn push_alpha(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); b.iter(|| { v.clear(); while !v.is_full() { @@ -69,7 +69,7 @@ fn push_alpha(b: &mut Bencher) { } fn push_string(b: &mut Bencher) { - let mut v = ArrayString::<[u8; 512]>::new(); + let mut v = ArrayString::<512>::new(); let input = "abcαβγ“”"; b.iter(|| { v.clear(); diff --git a/benches/extend.rs b/benches/extend.rs index 05797176..ba33a932 100644 --- a/benches/extend.rs +++ b/benches/extend.rs @@ -10,7 +10,7 @@ use bencher::Bencher; use bencher::black_box; fn extend_with_constant(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::::new(); let cap = v.capacity(); b.iter(|| { v.clear(); @@ -22,7 +22,7 @@ fn extend_with_constant(b: &mut Bencher) { } fn extend_with_range(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::::new(); let cap = v.capacity(); b.iter(|| { v.clear(); @@ -34,7 +34,7 @@ fn extend_with_range(b: &mut Bencher) { } fn extend_with_slice(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::::new(); let data = [1; 512]; b.iter(|| { v.clear(); @@ -46,7 +46,7 @@ fn extend_with_slice(b: &mut Bencher) { } fn extend_with_write(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::::new(); let data = [1; 512]; b.iter(|| { v.clear(); @@ -57,7 +57,7 @@ fn extend_with_write(b: &mut Bencher) { } fn extend_from_slice(b: &mut Bencher) { - let mut v = ArrayVec::<[u8; 512]>::new(); + let mut v = ArrayVec::::new(); let data = [1; 512]; b.iter(|| { v.clear(); diff --git a/src/array.rs b/src/array.rs deleted file mode 100644 index 2de5e77c..00000000 --- a/src/array.rs +++ /dev/null @@ -1,151 +0,0 @@ - -/// Trait for fixed size arrays. -/// -/// This trait is implemented for some specific array sizes, see -/// the implementor list below. At the current state of Rust we can't -/// make this fully general for every array size. -/// -/// The following crate features add more array sizes (and they are not -/// enabled by default due to their impact on compliation speed). -/// -/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented -/// (a few in this range are included by default). -/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented -/// (a few in this range are included by default). -/// -/// ## Safety -/// -/// This trait can *only* be implemented by fixed-size arrays or types with -/// *exactly* the representation of a fixed size array (of the right element -/// type and capacity). -/// -/// Normally this trait is an implementation detail of arrayvec and doesn’t -/// need implementing. -pub unsafe trait Array { - /// The array’s element type - type Item; - /// The smallest type that can index and tell the length of the array. - #[doc(hidden)] - type Index: Index; - /// The array's element capacity - const CAPACITY: usize; - fn as_slice(&self) -> &[Self::Item]; - fn as_mut_slice(&mut self) -> &mut [Self::Item]; -} - -pub trait Index : PartialEq + Copy { - const ZERO: Self; - fn to_usize(self) -> usize; - fn from(_: usize) -> Self; -} - -impl Index for () { - const ZERO: Self = (); - #[inline(always)] - fn to_usize(self) -> usize { 0 } - #[inline(always)] - fn from(_ix: usize) -> Self { () } -} - -impl Index for bool { - const ZERO: Self = false; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix != 0 } -} - -impl Index for u8 { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix as u8 } -} - -impl Index for u16 { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix as u16 } -} - -impl Index for u32 { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self as usize } - #[inline(always)] - fn from(ix: usize) -> Self { ix as u32 } -} - -impl Index for usize { - const ZERO: Self = 0; - #[inline(always)] - fn to_usize(self) -> usize { self } - #[inline(always)] - fn from(ix: usize) -> Self { ix } -} - -macro_rules! fix_array_impl { - ($index_type:ty, $len:expr ) => ( - unsafe impl Array for [T; $len] { - type Item = T; - type Index = $index_type; - const CAPACITY: usize = $len; - #[doc(hidden)] - fn as_slice(&self) -> &[Self::Item] { self } - #[doc(hidden)] - fn as_mut_slice(&mut self) -> &mut [Self::Item] { self } - } - ) -} - -macro_rules! fix_array_impl_recursive { - ($index_type:ty, ) => (); - ($index_type:ty, $($len:expr,)*) => ( - $(fix_array_impl!($index_type, $len);)* - ); -} - - -fix_array_impl_recursive!((), 0,); -fix_array_impl_recursive!(bool, 1,); -fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, ); - -#[cfg(not(feature="array-sizes-33-128"))] -fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, ); - -#[cfg(feature="array-sizes-33-128")] -fix_array_impl_recursive!(u8, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, -72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, -109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, -125, 126, 127, 128, -); - -#[cfg(not(feature="array-sizes-129-255"))] -fix_array_impl_recursive!(u8, 160, 192, 200, 224,); - -#[cfg(feature="array-sizes-129-255")] -fix_array_impl_recursive!(u8, -129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, -141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, -157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, -173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, -189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, -205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, -221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, -237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, -253, 254, 255, -); - -fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,); -// This array size doesn't exist on 16-bit -#[cfg(any(target_pointer_width="32", target_pointer_width="64"))] -fix_array_impl_recursive!(u32, 1 << 16,); - diff --git a/src/array_string.rs b/src/array_string.rs index 48139b21..c642e2bd 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -3,6 +3,7 @@ use std::cmp; use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; +use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; use std::ptr; use std::slice; @@ -10,16 +11,12 @@ use std::str; use std::str::FromStr; use std::str::Utf8Error; -use crate::array::Array; -use crate::array::Index; use crate::CapacityError; use crate::char::encode_utf8; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use super::MaybeUninit as MaybeUninitCopy; - /// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track @@ -28,24 +25,21 @@ use super::MaybeUninit as MaybeUninitCopy; /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] -pub struct ArrayString - where A: Array + Copy -{ - xs: MaybeUninitCopy, - len: A::Index, +pub struct ArrayString { + // the `len` first elements of the array are initialized + xs: [MaybeUninit; CAP], + len: usize, } -impl Default for ArrayString - where A: Array + Copy +impl Default for ArrayString { /// Return an empty `ArrayString` - fn default() -> ArrayString { + fn default() -> ArrayString { ArrayString::new() } } -impl ArrayString - where A: Array + Copy +impl ArrayString { /// Create a new empty `ArrayString`. /// @@ -54,34 +48,28 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 16]>::new(); + /// let mut string = ArrayString::<16>::new(); /// string.push_str("foo"); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` #[cfg(not(feature="unstable-const-fn"))] - pub fn new() -> ArrayString { + pub fn new() -> ArrayString { unsafe { - ArrayString { - xs: MaybeUninitCopy::uninitialized(), - len: Index::ZERO, - } + ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } #[cfg(feature="unstable-const-fn")] - pub const fn new() -> ArrayString { + pub const fn new() -> ArrayString { unsafe { - ArrayString { - xs: MaybeUninitCopy::uninitialized(), - len: Index::ZERO, - } + ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } /// Return the length of the string. #[inline] - pub fn len(&self) -> usize { self.len.to_usize() } + pub fn len(&self) -> usize { self.len } /// Returns whether the string is empty. #[inline] @@ -96,7 +84,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut string = ArrayString::<3>::from("foo").unwrap(); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.len(), 3); /// assert_eq!(string.capacity(), 3); @@ -116,13 +104,16 @@ impl ArrayString /// /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); /// ``` - pub fn from_byte_string(b: &A) -> Result { - let len = str::from_utf8(b.as_slice())?.len(); - debug_assert_eq!(len, A::CAPACITY); - Ok(ArrayString { - xs: MaybeUninitCopy::from(*b), - len: Index::from(A::CAPACITY), - }) + pub fn from_byte_string(b: &[u8; CAP]) -> Result { + let len = str::from_utf8(b)?.len(); + debug_assert_eq!(len, CAP); + let mut vec = Self::new(); + unsafe { + (b as *const [u8; CAP] as *const [MaybeUninit; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); + vec.set_len(CAP); + } + Ok(vec) } /// Return the capacity of the `ArrayString`. @@ -130,18 +121,18 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let string = ArrayString::<[_; 3]>::new(); + /// let string = ArrayString::<3>::new(); /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] - pub fn capacity(&self) -> usize { A::CAPACITY } + pub fn capacity(&self) -> usize { CAP } /// Return if the `ArrayString` is completely filled. /// /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 1]>::new(); + /// let mut string = ArrayString::<1>::new(); /// assert!(!string.is_full()); /// string.push_str("A"); /// assert!(string.is_full()); @@ -155,7 +146,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.push('a'); /// string.push('b'); @@ -175,7 +166,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.try_push('a').unwrap(); /// string.try_push('b').unwrap(); @@ -187,7 +178,7 @@ impl ArrayString pub fn try_push(&mut self, c: char) -> Result<(), CapacityError> { let len = self.len(); unsafe { - let ptr = self.xs.ptr_mut().add(len); + let ptr = self.as_mut_ptr().add(len); let remaining_cap = self.capacity() - len; match encode_utf8(c, ptr, remaining_cap) { Ok(n) => { @@ -206,7 +197,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.push_str("a"); /// string.push_str("d"); @@ -226,7 +217,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.try_push_str("a").unwrap(); /// let overflow1 = string.try_push_str("bc"); @@ -242,7 +233,7 @@ impl ArrayString return Err(CapacityError::new(s)); } unsafe { - let dst = self.xs.ptr_mut().add(self.len()); + let dst = self.as_mut_ptr().add(self.len()); let src = s.as_ptr(); ptr::copy_nonoverlapping(src, dst, s.len()); let newl = self.len() + s.len(); @@ -258,7 +249,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); @@ -288,7 +279,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 6]>::from("foobar").unwrap(); + /// let mut string = ArrayString::<6>::from("foobar").unwrap(); /// string.truncate(3); /// assert_eq!(&string[..], "foo"); /// string.truncate(4); @@ -318,7 +309,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); @@ -333,8 +324,8 @@ impl ArrayString let next = idx + ch.len_utf8(); let len = self.len(); unsafe { - ptr::copy(self.xs.ptr().add(next), - self.xs.ptr_mut().add(idx), + ptr::copy(self.as_ptr().add(next), + self.as_mut_ptr().add(idx), len - next); self.set_len(len - (next - idx)); } @@ -357,103 +348,99 @@ impl ArrayString /// and may use other debug assertions. pub unsafe fn set_len(&mut self, length: usize) { debug_assert!(length <= self.capacity()); - self.len = Index::from(length); + self.len = length; } /// Return a string slice of the whole `ArrayString`. pub fn as_str(&self) -> &str { self } + + fn as_ptr(&self) -> *const u8 { + self.xs.as_ptr() as *const u8 + } + + fn as_mut_ptr(&mut self) -> *mut u8 { + self.xs.as_mut_ptr() as *mut u8 + } } -impl Deref for ArrayString - where A: Array + Copy +impl Deref for ArrayString { type Target = str; #[inline] fn deref(&self) -> &str { unsafe { - let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize()); + let sl = slice::from_raw_parts(self.as_ptr(), self.len); str::from_utf8_unchecked(sl) } } } -impl DerefMut for ArrayString - where A: Array + Copy +impl DerefMut for ArrayString { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { - let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize()); + let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len); str::from_utf8_unchecked_mut(sl) } } } -impl PartialEq for ArrayString - where A: Array + Copy +impl PartialEq for ArrayString { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } -impl PartialEq for ArrayString - where A: Array + Copy +impl PartialEq for ArrayString { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } -impl PartialEq> for str - where A: Array + Copy +impl PartialEq> for str { - fn eq(&self, rhs: &ArrayString) -> bool { + fn eq(&self, rhs: &ArrayString) -> bool { self == &**rhs } } -impl Eq for ArrayString - where A: Array + Copy +impl Eq for ArrayString { } -impl Hash for ArrayString - where A: Array + Copy +impl Hash for ArrayString { fn hash(&self, h: &mut H) { (**self).hash(h) } } -impl Borrow for ArrayString - where A: Array + Copy +impl Borrow for ArrayString { fn borrow(&self) -> &str { self } } -impl AsRef for ArrayString - where A: Array + Copy +impl AsRef for ArrayString { fn as_ref(&self) -> &str { self } } -impl fmt::Debug for ArrayString - where A: Array + Copy +impl fmt::Debug for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl fmt::Display for ArrayString - where A: Array + Copy +impl fmt::Display for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } /// `Write` appends written data to the end of the string. -impl fmt::Write for ArrayString - where A: Array + Copy +impl fmt::Write for ArrayString { fn write_char(&mut self, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error) @@ -464,10 +451,9 @@ impl fmt::Write for ArrayString } } -impl Clone for ArrayString - where A: Array + Copy +impl Clone for ArrayString { - fn clone(&self) -> ArrayString { + fn clone(&self) -> ArrayString { *self } fn clone_from(&mut self, rhs: &Self) { @@ -477,8 +463,7 @@ impl Clone for ArrayString } } -impl PartialOrd for ArrayString - where A: Array + Copy +impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &Self) -> Option { (**self).partial_cmp(&**rhs) @@ -489,8 +474,7 @@ impl PartialOrd for ArrayString fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } } -impl PartialOrd for ArrayString - where A: Array + Copy +impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &str) -> Option { (**self).partial_cmp(rhs) @@ -501,28 +485,25 @@ impl PartialOrd for ArrayString fn ge(&self, rhs: &str) -> bool { &**self >= rhs } } -impl PartialOrd> for str - where A: Array + Copy +impl PartialOrd> for str { - fn partial_cmp(&self, rhs: &ArrayString) -> Option { + fn partial_cmp(&self, rhs: &ArrayString) -> Option { self.partial_cmp(&**rhs) } - fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } - fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } - fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } - fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } + fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } + fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } + fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } + fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } } -impl Ord for ArrayString - where A: Array + Copy +impl Ord for ArrayString { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } -impl FromStr for ArrayString - where A: Array + Copy +impl FromStr for ArrayString { type Err = CapacityError; @@ -533,8 +514,7 @@ impl FromStr for ArrayString #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl Serialize for ArrayString - where A: Array + Copy +impl Serialize for ArrayString { fn serialize(&self, serializer: S) -> Result where S: Serializer @@ -545,8 +525,7 @@ impl Serialize for ArrayString #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<'de, A> Deserialize<'de> for ArrayString - where A: Array + Copy +impl<'de, const CAP: usize> Deserialize<'de> for ArrayString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> @@ -554,13 +533,13 @@ impl<'de, A> Deserialize<'de> for ArrayString use serde::de::{self, Visitor}; use std::marker::PhantomData; - struct ArrayStringVisitor>(PhantomData); + struct ArrayStringVisitor(PhantomData<[u8; CAP]>); - impl<'de, A: Copy + Array> Visitor<'de> for ArrayStringVisitor { - type Value = ArrayString; + impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor { + type Value = ArrayString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a string no more than {} bytes long", A::CAPACITY) + write!(formatter, "a string no more than {} bytes long", CAP) } fn visit_str(self, v: &str) -> Result @@ -578,13 +557,11 @@ impl<'de, A> Deserialize<'de> for ArrayString } } - deserializer.deserialize_str(ArrayStringVisitor::(PhantomData)) + deserializer.deserialize_str(ArrayStringVisitor(PhantomData)) } } -impl<'a, A> TryFrom<&'a str> for ArrayString -where - A: Array + Copy +impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString { type Error = CapacityError<&'a str>; @@ -595,9 +572,7 @@ where } } -impl<'a, A> TryFrom> for ArrayString -where - A: Array + Copy +impl<'a, const CAP: usize> TryFrom> for ArrayString { type Error = CapacityError; diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 1f168f9f..c7c4a2ce 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -14,15 +14,14 @@ use std::fmt; #[cfg(feature="std")] use std::io; -use crate::maybe_uninit::MaybeUninit; - +use std::mem::ManuallyDrop; +use std::mem::MaybeUninit; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use crate::array::Array; use crate::errors::CapacityError; -use crate::array::Index; +use crate::arrayvec_impl::ArrayVecImpl; /// A vector with a fixed capacity. /// @@ -36,12 +35,13 @@ use crate::array::Index; /// that the full slice API is available. /// /// ArrayVec can be converted into a by value iterator. -pub struct ArrayVec { - xs: MaybeUninit, - len: A::Index, +pub struct ArrayVec { + // the `len` first elements of the array are initialized + xs: [MaybeUninit; CAP], + len: usize, } -impl Drop for ArrayVec { +impl Drop for ArrayVec { fn drop(&mut self) { self.clear(); @@ -56,7 +56,10 @@ macro_rules! panic_oob { } } -impl ArrayVec { +impl ArrayVec { + /// Capacity + const CAPACITY: usize = CAP; + /// Create a new empty `ArrayVec`. /// /// Capacity is inferred from the type parameter. @@ -64,23 +67,23 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 16]>::new(); + /// let mut array = ArrayVec::<_, 16>::new(); /// array.push(1); /// array.push(2); /// assert_eq!(&array[..], &[1, 2]); /// assert_eq!(array.capacity(), 16); /// ``` #[cfg(not(feature="unstable-const-fn"))] - pub fn new() -> ArrayVec { + pub fn new() -> ArrayVec { unsafe { - ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } + ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } #[cfg(feature="unstable-const-fn")] - pub const fn new() -> ArrayVec { + pub const fn new() -> ArrayVec { unsafe { - ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } + ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } @@ -94,7 +97,7 @@ impl ArrayVec { /// assert_eq!(array.len(), 2); /// ``` #[inline] - pub fn len(&self) -> usize { self.len.to_usize() } + pub fn len(&self) -> usize { self.len as usize } /// Returns whether the `ArrayVec` is empty. /// @@ -117,14 +120,14 @@ impl ArrayVec { /// assert_eq!(array.capacity(), 3); /// ``` #[inline(always)] - pub fn capacity(&self) -> usize { A::CAPACITY } + pub fn capacity(&self) -> usize { CAP } /// Return if the `ArrayVec` is completely filled. /// /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 1]>::new(); + /// let mut array = ArrayVec::<_, 1>::new(); /// assert!(!array.is_full()); /// array.push(1); /// assert!(array.is_full()); @@ -151,15 +154,15 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// array.push(1); /// array.push(2); /// /// assert_eq!(&array[..], &[1, 2]); /// ``` - pub fn push(&mut self, element: A::Item) { - self.try_push(element).unwrap() + pub fn push(&mut self, element: T) { + ArrayVecImpl::push(self, element) } /// Push `element` to the end of the vector. @@ -170,7 +173,7 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// let push1 = array.try_push(1); /// let push2 = array.try_push(2); @@ -184,18 +187,10 @@ impl ArrayVec { /// /// assert!(overflow.is_err()); /// ``` - pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError> { - if self.len() < A::CAPACITY { - unsafe { - self.push_unchecked(element); - } - Ok(()) - } else { - Err(CapacityError::new(element)) - } + pub fn try_push(&mut self, element: T) -> Result<(), CapacityError> { + ArrayVecImpl::try_push(self, element) } - /// Push `element` to the end of the vector without checking the capacity. /// /// It is up to the caller to ensure the capacity of the vector is @@ -206,7 +201,7 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// if array.len() + 2 <= array.capacity() { /// unsafe { @@ -217,16 +212,38 @@ impl ArrayVec { /// /// assert_eq!(&array[..], &[1, 2]); /// ``` - pub unsafe fn push_unchecked(&mut self, element: A::Item) { - let len = self.len(); - debug_assert!(len < A::CAPACITY); - ptr::write(self.get_unchecked_ptr(len), element); - self.set_len(len + 1); + pub unsafe fn push_unchecked(&mut self, element: T) { + ArrayVecImpl::push_unchecked(self, element) + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector’s current length this has no + /// effect. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); + /// array.truncate(3); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// array.truncate(4); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// ``` + pub fn truncate(&mut self, new_len: usize) { + ArrayVecImpl::truncate(self, new_len) } + /// Remove all elements in the vector. + pub fn clear(&mut self) { + ArrayVecImpl::clear(self) + } + + /// Get pointer to where element at `index` would be - unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut A::Item { - self.xs.ptr_mut().add(index) + unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T { + self.as_mut_ptr().add(index) } /// Insert `element` at position `index`. @@ -242,14 +259,14 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// array.insert(0, "x"); /// array.insert(0, "y"); /// assert_eq!(&array[..], &["y", "x"]); /// /// ``` - pub fn insert(&mut self, index: usize, element: A::Item) { + pub fn insert(&mut self, index: usize, element: T) { self.try_insert(index, element).unwrap() } @@ -265,7 +282,7 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// assert!(array.try_insert(0, "x").is_ok()); /// assert!(array.try_insert(0, "y").is_ok()); @@ -273,7 +290,7 @@ impl ArrayVec { /// assert_eq!(&array[..], &["y", "x"]); /// /// ``` - pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityError> { + pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), CapacityError> { if index > self.len() { panic_oob!("try_insert", index, self.len()) } @@ -306,22 +323,15 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// array.push(1); /// /// assert_eq!(array.pop(), Some(1)); /// assert_eq!(array.pop(), None); /// ``` - pub fn pop(&mut self) -> Option { - if self.len() == 0 { - return None; - } - unsafe { - let new_len = self.len() - 1; - self.set_len(new_len); - Some(ptr::read(self.get_unchecked_ptr(new_len))) - } + pub fn pop(&mut self) -> Option { + ArrayVecImpl::pop(self) } /// Remove the element at `index` and swap the last element into its place. @@ -343,7 +353,7 @@ impl ArrayVec { /// assert_eq!(array.swap_remove(1), 2); /// assert_eq!(&array[..], &[3]); /// ``` - pub fn swap_remove(&mut self, index: usize) -> A::Item { + pub fn swap_remove(&mut self, index: usize) -> T { self.swap_pop(index) .unwrap_or_else(|| { panic_oob!("swap_remove", index, self.len()) @@ -367,7 +377,7 @@ impl ArrayVec { /// /// assert_eq!(array.swap_pop(10), None); /// ``` - pub fn swap_pop(&mut self, index: usize) -> Option { + pub fn swap_pop(&mut self, index: usize) -> Option { let len = self.len(); if index >= len { return None; @@ -391,7 +401,7 @@ impl ArrayVec { /// assert_eq!(removed_elt, 1); /// assert_eq!(&array[..], &[2, 3]); /// ``` - pub fn remove(&mut self, index: usize) -> A::Item { + pub fn remove(&mut self, index: usize) -> T { self.pop_at(index) .unwrap_or_else(|| { panic_oob!("remove", index, self.len()) @@ -414,7 +424,7 @@ impl ArrayVec { /// assert!(array.pop_at(2).is_none()); /// assert!(array.pop_at(10).is_none()); /// ``` - pub fn pop_at(&mut self, index: usize) -> Option { + pub fn pop_at(&mut self, index: usize) -> Option { if index >= self.len() { None } else { @@ -422,36 +432,6 @@ impl ArrayVec { } } - /// Shortens the vector, keeping the first `len` elements and dropping - /// the rest. - /// - /// If `len` is greater than the vector’s current length this has no - /// effect. - /// - /// ``` - /// use arrayvec::ArrayVec; - /// - /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); - /// array.truncate(3); - /// assert_eq!(&array[..], &[1, 2, 3]); - /// array.truncate(4); - /// assert_eq!(&array[..], &[1, 2, 3]); - /// ``` - pub fn truncate(&mut self, new_len: usize) { - unsafe { - if new_len < self.len() { - let tail: *mut [_] = &mut self[new_len..]; - self.len = Index::from(new_len); - ptr::drop_in_place(tail); - } - } - } - - /// Remove all elements in the vector. - pub fn clear(&mut self) { - self.truncate(0) - } - /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&mut e)` returns false. @@ -466,7 +446,7 @@ impl ArrayVec { /// assert_eq!(&array[..], &[1, 3]); /// ``` pub fn retain(&mut self, mut f: F) - where F: FnMut(&mut A::Item) -> bool + where F: FnMut(&mut T) -> bool { let len = self.len(); let mut del = 0; @@ -495,7 +475,7 @@ impl ArrayVec { /// not greater than the capacity. pub unsafe fn set_len(&mut self, length: usize) { debug_assert!(length <= self.capacity()); - self.len = Index::from(length); + self.len = length; } /// Copy and appends all elements in a slice to the `ArrayVec`. @@ -503,7 +483,7 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + /// let mut vec: ArrayVec = ArrayVec::new(); /// vec.push(1); /// vec.try_extend_from_slice(&[2, 3]).unwrap(); /// assert_eq!(&vec[..], &[1, 2, 3]); @@ -516,8 +496,8 @@ impl ArrayVec { /// slice. /// /// [`remaining_capacity`]: #method.remaining_capacity - pub fn try_extend_from_slice(&mut self, other: &[A::Item]) -> Result<(), CapacityError> - where A::Item: Copy, + pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError> + where T: Copy, { if self.remaining_capacity() < other.len() { return Err(CapacityError::new(())); @@ -527,7 +507,7 @@ impl ArrayVec { let other_len = other.len(); unsafe { - let dst = self.xs.ptr_mut().add(self_len); + let dst = self.get_unchecked_ptr(self_len); ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); self.set_len(self_len + other_len); } @@ -548,11 +528,11 @@ impl ArrayVec { /// use arrayvec::ArrayVec; /// /// let mut v = ArrayVec::from([1, 2, 3]); - /// let u: ArrayVec<[_; 3]> = v.drain(0..2).collect(); + /// let u: ArrayVec<_, 3> = v.drain(0..2).collect(); /// assert_eq!(&v[..], &[3]); /// assert_eq!(&u[..], &[1, 2]); /// ``` - pub fn drain(&mut self, range: R) -> Drain + pub fn drain(&mut self, range: R) -> Drain where R: RangeBounds { // Memory safety @@ -579,7 +559,7 @@ impl ArrayVec { self.drain_range(start, end) } - fn drain_range(&mut self, start: usize, end: usize) -> Drain + fn drain_range(&mut self, start: usize, end: usize) -> Drain { let len = self.len(); @@ -588,7 +568,7 @@ impl ArrayVec { // Calling `set_len` creates a fresh and thus unique mutable references, making all // older aliases we created invalid. So we cannot call that function. - self.len = Index::from(start); + self.len = start; unsafe { Drain { @@ -604,12 +584,12 @@ impl ArrayVec { /// /// Return an `Ok` value with the array if length equals capacity, /// return an `Err` with self otherwise. - pub fn into_inner(self) -> Result { + pub fn into_inner(self) -> Result<[T; CAP], Self> { if self.len() < self.capacity() { Err(self) } else { unsafe { - let array = ptr::read(self.xs.ptr() as *const A); + let array = ptr::read(self.as_ptr() as *const [T; CAP]); mem::forget(self); Ok(array) } @@ -624,46 +604,62 @@ impl ArrayVec { } /// Return a slice containing all elements of the vector. - pub fn as_slice(&self) -> &[A::Item] { - self + pub fn as_slice(&self) -> &[T] { + ArrayVecImpl::as_slice(self) } /// Return a mutable slice containing all elements of the vector. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { - self + pub fn as_mut_slice(&mut self) -> &mut [T] { + ArrayVecImpl::as_mut_slice(self) } /// Return a raw pointer to the vector's buffer. - pub fn as_ptr(&self) -> *const A::Item { - self.xs.ptr() + pub fn as_ptr(&self) -> *const T { + ArrayVecImpl::as_ptr(self) } /// Return a raw mutable pointer to the vector's buffer. - pub fn as_mut_ptr(&mut self) -> *mut A::Item { - self.xs.ptr_mut() + pub fn as_mut_ptr(&mut self) -> *mut T { + ArrayVecImpl::as_mut_ptr(self) } } -impl Deref for ArrayVec { - type Target = [A::Item]; +impl ArrayVecImpl for ArrayVec { + type Item = T; + const CAPACITY: usize = CAP; + + fn len(&self) -> usize { self.len() } + + unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= CAP); + self.len = length; + } + + fn as_ptr(&self) -> *const Self::Item { + self.xs.as_ptr() as _ + } + + fn as_mut_ptr(&mut self) -> *mut Self::Item { + self.xs.as_mut_ptr() as _ + } +} + +impl Deref for ArrayVec { + type Target = [T]; #[inline] - fn deref(&self) -> &[A::Item] { - unsafe { - slice::from_raw_parts(self.xs.ptr(), self.len()) - } + fn deref(&self) -> &Self::Target { + self.as_slice() } } -impl DerefMut for ArrayVec { +impl DerefMut for ArrayVec { #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { - let len = self.len(); - unsafe { - slice::from_raw_parts_mut(self.xs.ptr_mut(), len) - } + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() } } + /// Create an `ArrayVec` from an array. /// /// ``` @@ -673,9 +669,16 @@ impl DerefMut for ArrayVec { /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 3); /// ``` -impl From for ArrayVec { - fn from(array: A) -> Self { - ArrayVec { xs: MaybeUninit::from(array), len: Index::from(A::CAPACITY) } +impl From<[T; CAP]> for ArrayVec { + fn from(array: [T; CAP]) -> Self { + let array = ManuallyDrop::new(array); + let mut vec = >::new(); + unsafe { + (&*array as *const [T; CAP] as *const [MaybeUninit; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); + vec.set_len(CAP); + } + vec } } @@ -687,18 +690,17 @@ impl From for ArrayVec { /// use arrayvec::ArrayVec; /// use std::convert::TryInto as _; /// -/// let array: ArrayVec<[_; 4]> = (&[1, 2, 3] as &[_]).try_into().unwrap(); +/// let array: ArrayVec<_, 4> = (&[1, 2, 3] as &[_]).try_into().unwrap(); /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 4); /// ``` -impl std::convert::TryFrom<&[A::Item]> for ArrayVec - where - A::Item: Clone, +impl std::convert::TryFrom<&[T]> for ArrayVec + where T: Clone, { type Error = CapacityError; - fn try_from(slice: &[A::Item]) -> Result { - if A::CAPACITY < slice.len() { + fn try_from(slice: &[T]) -> Result { + if Self::CAPACITY < slice.len() { Err(CapacityError::new(())) } else { let mut array = Self::new(); @@ -720,9 +722,9 @@ impl std::convert::TryFrom<&[A::Item]> for ArrayVec /// // ... /// } /// ``` -impl<'a, A: Array> IntoIterator for &'a ArrayVec { - type Item = &'a A::Item; - type IntoIter = slice::Iter<'a, A::Item>; +impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec { + type Item = &'a T; + type IntoIter = slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } } @@ -737,9 +739,9 @@ impl<'a, A: Array> IntoIterator for &'a ArrayVec { /// // ... /// } /// ``` -impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { - type Item = &'a mut A::Item; - type IntoIter = slice::IterMut<'a, A::Item>; +impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec { + type Item = &'a mut T; + type IntoIter = slice::IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } @@ -754,44 +756,44 @@ impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { /// // ... /// } /// ``` -impl IntoIterator for ArrayVec { - type Item = A::Item; - type IntoIter = IntoIter; - fn into_iter(self) -> IntoIter { - IntoIter { index: Index::from(0), v: self, } +impl IntoIterator for ArrayVec { + type Item = T; + type IntoIter = IntoIter; + fn into_iter(self) -> IntoIter { + IntoIter { index: 0, v: self, } } } /// By-value iterator for `ArrayVec`. -pub struct IntoIter { - index: A::Index, - v: ArrayVec, +pub struct IntoIter { + index: usize, + v: ArrayVec, } -impl Iterator for IntoIter { - type Item = A::Item; +impl Iterator for IntoIter { + type Item = T; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.index == self.v.len { None } else { unsafe { - let index = self.index.to_usize(); - self.index = Index::from(index + 1); + let index = self.index; + self.index = index + 1; Some(ptr::read(self.v.get_unchecked_ptr(index))) } } } fn size_hint(&self) -> (usize, Option) { - let len = self.v.len() - self.index.to_usize(); + let len = self.v.len() - self.index; (len, Some(len)) } } -impl DoubleEndedIterator for IntoIter { - fn next_back(&mut self) -> Option { +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { if self.index == self.v.len { None } else { @@ -804,12 +806,12 @@ impl DoubleEndedIterator for IntoIter { } } -impl ExactSizeIterator for IntoIter { } +impl ExactSizeIterator for IntoIter { } -impl Drop for IntoIter { +impl Drop for IntoIter { fn drop(&mut self) { // panic safety: Set length to 0 before dropping elements. - let index = self.index.to_usize(); + let index = self.index; let len = self.v.len(); unsafe { self.v.set_len(0); @@ -821,51 +823,45 @@ impl Drop for IntoIter { } } -impl Clone for IntoIter -where - A::Item: Clone, +impl Clone for IntoIter +where T: Clone, { - fn clone(&self) -> IntoIter { - self.v[self.index.to_usize()..] + fn clone(&self) -> IntoIter { + self.v[self.index..] .iter() .cloned() - .collect::>() + .collect::>() .into_iter() } } -impl fmt::Debug for IntoIter +impl fmt::Debug for IntoIter where - A::Item: fmt::Debug, + T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() - .entries(&self.v[self.index.to_usize()..]) + .entries(&self.v[self.index..]) .finish() } } /// A draining iterator for `ArrayVec`. -pub struct Drain<'a, A> - where A: Array, - A::Item: 'a, -{ +pub struct Drain<'a, T: 'a, const CAP: usize> { /// Index of tail to preserve tail_start: usize, /// Length of tail tail_len: usize, /// Current remaining range to remove - iter: slice::Iter<'a, A::Item>, - vec: *mut ArrayVec, + iter: slice::Iter<'a, T>, + vec: *mut ArrayVec, } -unsafe impl<'a, A: Array + Sync> Sync for Drain<'a, A> {} -unsafe impl<'a, A: Array + Send> Send for Drain<'a, A> {} +unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {} +unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {} -impl<'a, A: Array> Iterator for Drain<'a, A> - where A::Item: 'a, -{ - type Item = A::Item; +impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { + type Item = T; fn next(&mut self) -> Option { self.iter.next().map(|elt| @@ -880,8 +876,7 @@ impl<'a, A: Array> Iterator for Drain<'a, A> } } -impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> - where A::Item: 'a, +impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> { fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| @@ -892,11 +887,9 @@ impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> } } -impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} +impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {} -impl<'a, A: Array> Drop for Drain<'a, A> - where A::Item: 'a -{ +impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> { fn drop(&mut self) { // len is currently 0 so panicking while dropping will not cause a double drop. @@ -940,8 +933,8 @@ impl Drop for ScopeExitGuard /// /// Does not extract more items than there is space for. No error /// occurs if there are more iterator elements. -impl Extend for ArrayVec { - fn extend>(&mut self, iter: T) { +impl Extend for ArrayVec { + fn extend>(&mut self, iter: I) { let take = self.capacity() - self.len(); unsafe { let len = self.len(); @@ -955,7 +948,7 @@ impl Extend for ArrayVec { value: &mut self.len, data: len, f: move |&len, self_len| { - **self_len = Index::from(len); + **self_len = len; } }; let mut iter = iter.into_iter(); @@ -995,16 +988,16 @@ unsafe fn raw_ptr_write(ptr: *mut T, value: T) { /// /// Does not extract more items than there is space for. No error /// occurs if there are more iterator elements. -impl iter::FromIterator for ArrayVec { - fn from_iter>(iter: T) -> Self { +impl iter::FromIterator for ArrayVec { + fn from_iter>(iter: I) -> Self { let mut array = ArrayVec::new(); array.extend(iter); array } } -impl Clone for ArrayVec - where A::Item: Clone +impl Clone for ArrayVec + where T: Clone { fn clone(&self) -> Self { self.iter().cloned().collect() @@ -1027,61 +1020,61 @@ impl Clone for ArrayVec } } -impl Hash for ArrayVec - where A::Item: Hash +impl Hash for ArrayVec + where T: Hash { fn hash(&self, state: &mut H) { Hash::hash(&**self, state) } } -impl PartialEq for ArrayVec - where A::Item: PartialEq +impl PartialEq for ArrayVec + where T: PartialEq { fn eq(&self, other: &Self) -> bool { **self == **other } } -impl PartialEq<[A::Item]> for ArrayVec - where A::Item: PartialEq +impl PartialEq<[T]> for ArrayVec + where T: PartialEq { - fn eq(&self, other: &[A::Item]) -> bool { + fn eq(&self, other: &[T]) -> bool { **self == *other } } -impl Eq for ArrayVec where A::Item: Eq { } +impl Eq for ArrayVec where T: Eq { } -impl Borrow<[A::Item]> for ArrayVec { - fn borrow(&self) -> &[A::Item] { self } +impl Borrow<[T]> for ArrayVec { + fn borrow(&self) -> &[T] { self } } -impl BorrowMut<[A::Item]> for ArrayVec { - fn borrow_mut(&mut self) -> &mut [A::Item] { self } +impl BorrowMut<[T]> for ArrayVec { + fn borrow_mut(&mut self) -> &mut [T] { self } } -impl AsRef<[A::Item]> for ArrayVec { - fn as_ref(&self) -> &[A::Item] { self } +impl AsRef<[T]> for ArrayVec { + fn as_ref(&self) -> &[T] { self } } -impl AsMut<[A::Item]> for ArrayVec { - fn as_mut(&mut self) -> &mut [A::Item] { self } +impl AsMut<[T]> for ArrayVec { + fn as_mut(&mut self) -> &mut [T] { self } } -impl fmt::Debug for ArrayVec where A::Item: fmt::Debug { +impl fmt::Debug for ArrayVec where T: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl Default for ArrayVec { +impl Default for ArrayVec { /// Return an empty array - fn default() -> ArrayVec { + fn default() -> ArrayVec { ArrayVec::new() } } -impl PartialOrd for ArrayVec where A::Item: PartialOrd { - fn partial_cmp(&self, other: &ArrayVec) -> Option { +impl PartialOrd for ArrayVec where T: PartialOrd { + fn partial_cmp(&self, other: &Self) -> Option { (**self).partial_cmp(other) } @@ -1102,8 +1095,8 @@ impl PartialOrd for ArrayVec where A::Item: PartialOrd { } } -impl Ord for ArrayVec where A::Item: Ord { - fn cmp(&self, other: &ArrayVec) -> cmp::Ordering { +impl Ord for ArrayVec where T: Ord { + fn cmp(&self, other: &Self) -> cmp::Ordering { (**self).cmp(other) } } @@ -1112,7 +1105,7 @@ impl Ord for ArrayVec where A::Item: Ord { /// `Write` appends written data to the end of the vector. /// /// Requires `features="std"`. -impl> io::Write for ArrayVec { +impl io::Write for ArrayVec { fn write(&mut self, data: &[u8]) -> io::Result { let len = cmp::min(self.remaining_capacity(), data.len()); let _result = self.try_extend_from_slice(&data[..len]); @@ -1124,7 +1117,7 @@ impl> io::Write for ArrayVec { #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl> Serialize for ArrayVec { +impl Serialize for ArrayVec { fn serialize(&self, serializer: S) -> Result where S: Serializer { @@ -1134,30 +1127,30 @@ impl> Serialize for ArrayVec { #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<'de, T: Deserialize<'de>, A: Array> Deserialize<'de> for ArrayVec { +impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { use serde::de::{Visitor, SeqAccess, Error}; use std::marker::PhantomData; - struct ArrayVecVisitor<'de, T: Deserialize<'de>, A: Array>(PhantomData<(&'de (), T, A)>); + struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>); - impl<'de, T: Deserialize<'de>, A: Array> Visitor<'de> for ArrayVecVisitor<'de, T, A> { - type Value = ArrayVec; + impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> { + type Value = ArrayVec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "an array with no more than {} items", A::CAPACITY) + write!(formatter, "an array with no more than {} items", CAP) } fn visit_seq(self, mut seq: SA) -> Result where SA: SeqAccess<'de>, { - let mut values = ArrayVec::::new(); + let mut values = ArrayVec::::new(); while let Some(value) = seq.next_element()? { if let Err(_) = values.try_push(value) { - return Err(SA::Error::invalid_length(A::CAPACITY + 1, &self)); + return Err(SA::Error::invalid_length(CAP + 1, &self)); } } @@ -1165,6 +1158,6 @@ impl<'de, T: Deserialize<'de>, A: Array> Deserialize<'de> for ArrayVec(PhantomData)) + deserializer.deserialize_seq(ArrayVecVisitor::(PhantomData)) } } diff --git a/src/arrayvec_impl.rs b/src/arrayvec_impl.rs new file mode 100644 index 00000000..6c09834a --- /dev/null +++ b/src/arrayvec_impl.rs @@ -0,0 +1,86 @@ +use std::ptr; +use std::slice; + +use crate::CapacityError; + +/// Implements basic arrayvec methods - based on a few required methods +/// for length and element access. +pub(crate) trait ArrayVecImpl { + type Item; + const CAPACITY: usize; + + fn len(&self) -> usize; + + unsafe fn set_len(&mut self, new_len: usize); + + /// Return a slice containing all elements of the vector. + fn as_slice(&self) -> &[Self::Item] { + let len = self.len(); + unsafe { + slice::from_raw_parts(self.as_ptr(), len) + } + } + + /// Return a mutable slice containing all elements of the vector. + fn as_mut_slice(&mut self) -> &mut [Self::Item] { + let len = self.len(); + unsafe { + std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } + } + + /// Return a raw pointer to the vector's buffer. + fn as_ptr(&self) -> *const Self::Item; + + /// Return a raw mutable pointer to the vector's buffer. + fn as_mut_ptr(&mut self) -> *mut Self::Item; + + fn push(&mut self, element: Self::Item) { + self.try_push(element).unwrap() + } + + fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError> { + if self.len() < Self::CAPACITY { + unsafe { + self.push_unchecked(element); + } + Ok(()) + } else { + Err(CapacityError::new(element)) + } + } + + unsafe fn push_unchecked(&mut self, element: Self::Item) { + let len = self.len(); + debug_assert!(len < Self::CAPACITY); + ptr::write(self.as_mut_ptr().add(len), element); + self.set_len(len + 1); + } + + fn pop(&mut self) -> Option { + if self.len() == 0 { + return None; + } + unsafe { + let new_len = self.len() - 1; + self.set_len(new_len); + Some(ptr::read(self.as_ptr().add(new_len))) + } + } + + fn clear(&mut self) { + self.truncate(0) + } + + fn truncate(&mut self, new_len: usize) { + unsafe { + let len = self.len(); + if new_len < len { + self.set_len(new_len); + let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len); + ptr::drop_in_place(tail); + } + } + } +} + diff --git a/src/lib.rs b/src/lib.rs index d3bed603..e0a58173 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,9 +10,6 @@ //! - `serde` //! - Optional //! - Enable serialization for ArrayVec and ArrayString using serde 1.x -//! - `array-sizes-33-128`, `array-sizes-129-255` -//! - Optional -//! - Enable more array sizes (see [Array] for more information) //! //! - `unstable-const-fn` //! - Optional @@ -22,11 +19,11 @@ //! //! ## Rust Version //! -//! This version of arrayvec requires Rust 1.36 or later. +//! This version of arrayvec requires Rust 1.51 or later. //! #![doc(html_root_url="https://docs.rs/arrayvec/0.5/")] #![cfg_attr(not(feature="std"), no_std)] -#![cfg_attr(feature="unstable-const-fn", feature(const_fn))] +#![cfg_attr(feature="unstable-const-fn", feature(const_fn, const_maybe_uninit_assume_init))] #[cfg(feature="serde")] extern crate serde; @@ -34,19 +31,12 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -mod maybe_uninit; -use crate::maybe_uninit::MaybeUninit; - -#[cfg(feature="serde")] -use serde::{Serialize, Deserialize, Serializer, Deserializer}; - -mod array; +mod arrayvec_impl; mod arrayvec; mod array_string; mod char; mod errors; -pub use crate::array::Array; pub use crate::array_string::ArrayString; pub use crate::errors::CapacityError; diff --git a/src/maybe_uninit.rs b/src/maybe_uninit.rs deleted file mode 100644 index e009abfc..00000000 --- a/src/maybe_uninit.rs +++ /dev/null @@ -1,44 +0,0 @@ - - -use crate::array::Array; -use std::mem::MaybeUninit as StdMaybeUninit; - -#[derive(Copy)] -pub struct MaybeUninit { - inner: StdMaybeUninit, -} - -impl Clone for MaybeUninit - where T: Copy -{ - fn clone(&self) -> Self { *self } -} - -impl MaybeUninit { - /// Create a new MaybeUninit with uninitialized interior - pub const unsafe fn uninitialized() -> Self { - MaybeUninit { inner: StdMaybeUninit::uninit() } - } - - /// Create a new MaybeUninit from the value `v`. - pub fn from(v: T) -> Self { - MaybeUninit { inner: StdMaybeUninit::new(v) } - } - - // Raw pointer casts written so that we don't reference or access the - // uninitialized interior value - - /// Return a raw pointer to the start of the interior array - pub fn ptr(&self) -> *const T::Item - where T: Array - { - self.inner.as_ptr() as *const T::Item - } - - /// Return a mut raw pointer to the start of the interior array - pub fn ptr_mut(&mut self) -> *mut T::Item - where T: Array - { - self.inner.as_mut_ptr() as *mut T::Item - } -} diff --git a/tests/serde.rs b/tests/serde.rs index 3876d2a7..f02c693a 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -9,7 +9,7 @@ mod array_vec { #[test] fn test_ser_de_empty() { - let vec = ArrayVec::<[u32; 0]>::new(); + let vec = ArrayVec::::new(); assert_tokens(&vec, &[ Token::Seq { len: Some(0) }, @@ -20,7 +20,7 @@ mod array_vec { #[test] fn test_ser_de() { - let mut vec = ArrayVec::<[u32; 3]>::new(); + let mut vec = ArrayVec::::new(); vec.push(20); vec.push(55); vec.push(123); @@ -36,7 +36,7 @@ mod array_vec { #[test] fn test_de_too_large() { - assert_de_tokens_error::>(&[ + assert_de_tokens_error::>(&[ Token::Seq { len: Some(3) }, Token::U32(13), Token::U32(42), @@ -52,7 +52,7 @@ mod array_string { #[test] fn test_ser_de_empty() { - let string = ArrayString::<[u8; 0]>::new(); + let string = ArrayString::<0>::new(); assert_tokens(&string, &[ Token::Str(""), @@ -62,7 +62,7 @@ mod array_string { #[test] fn test_ser_de() { - let string = ArrayString::<[u8; 9]>::from("1234 abcd") + let string = ArrayString::<9>::from("1234 abcd") .expect("expected exact specified capacity to be enough"); assert_tokens(&string, &[ @@ -72,7 +72,7 @@ mod array_string { #[test] fn test_de_too_large() { - assert_de_tokens_error::>(&[ + assert_de_tokens_error::>(&[ Token::Str("afd") ], "invalid length 3, expected a string no more than 2 bytes long"); } diff --git a/tests/tests.rs b/tests/tests.rs index 593b5e41..676cd7cd 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; fn test_simple() { use std::ops::Add; - let mut vec: ArrayVec<[Vec; 3]> = ArrayVec::new(); + let mut vec: ArrayVec, 3> = ArrayVec::new(); vec.push(vec![1, 2, 3, 4]); vec.push(vec![10]); @@ -29,7 +29,7 @@ fn test_simple() { #[test] fn test_capacity_left() { - let mut vec: ArrayVec<[usize; 4]> = ArrayVec::new(); + let mut vec: ArrayVec = ArrayVec::new(); assert_eq!(vec.remaining_capacity(), 4); vec.push(1); assert_eq!(vec.remaining_capacity(), 3); @@ -43,7 +43,7 @@ fn test_capacity_left() { #[test] fn test_extend_from_slice() { - let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + let mut vec: ArrayVec = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); assert_eq!(vec.len(), 3); @@ -54,13 +54,13 @@ fn test_extend_from_slice() { #[test] fn test_extend_from_slice_error() { - let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + let mut vec: ArrayVec = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); let res = vec.try_extend_from_slice(&[0; 8]); assert_matches!(res, Err(_)); - let mut vec: ArrayVec<[usize; 0]> = ArrayVec::new(); + let mut vec: ArrayVec = ArrayVec::new(); let res = vec.try_extend_from_slice(&[0; 1]); assert_matches!(res, Err(_)); } @@ -70,14 +70,14 @@ fn test_try_from_slice_error() { use arrayvec::ArrayVec; use std::convert::TryInto as _; - let res: Result, _> = (&[1, 2, 3] as &[_]).try_into(); + let res: Result, _> = (&[1, 2, 3] as &[_]).try_into(); assert_matches!(res, Err(_)); } #[test] fn test_u16_index() { const N: usize = 4096; - let mut vec: ArrayVec<[_; N]> = ArrayVec::new(); + let mut vec: ArrayVec<_, N> = ArrayVec::new(); for _ in 0..N { assert!(vec.try_push(1u8).is_ok()); } @@ -113,7 +113,7 @@ fn test_drop() { } { - let mut array = ArrayVec::<[Bump; 128]>::new(); + let mut array = ArrayVec::::new(); array.push(Bump(flag)); array.push(Bump(flag)); } @@ -123,7 +123,7 @@ fn test_drop() { flag.set(0); { - let mut array = ArrayVec::<[_; 3]>::new(); + let mut array = ArrayVec::<_, 3>::new(); array.push(vec![Bump(flag)]); array.push(vec![Bump(flag), Bump(flag)]); array.push(vec![]); @@ -142,7 +142,7 @@ fn test_drop() { // test into_inner flag.set(0); { - let mut array = ArrayVec::<[_; 3]>::new(); + let mut array = ArrayVec::<_, 3>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -156,7 +156,7 @@ fn test_drop() { // test cloning into_iter flag.set(0); { - let mut array = ArrayVec::<[_; 3]>::new(); + let mut array = ArrayVec::<_, 3>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -210,7 +210,7 @@ fn test_drop_panics() { flag.set(0); { - let mut array = ArrayVec::<[Bump; 128]>::new(); + let mut array = ArrayVec::::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -226,7 +226,7 @@ fn test_drop_panics() { flag.set(0); { - let mut array = ArrayVec::<[Bump; 16]>::new(); + let mut array = ArrayVec::::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -251,14 +251,14 @@ fn test_drop_panics() { fn test_extend() { let mut range = 0..10; - let mut array: ArrayVec<[_; 5]> = range.by_ref().collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref()); assert_eq!(range.next(), Some(6)); - let mut array: ArrayVec<[_; 10]> = (0..3).collect(); + let mut array: ArrayVec<_, 10> = (0..3).collect(); assert_eq!(&array[..], &[0, 1, 2]); array.extend(3..5); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); @@ -266,33 +266,32 @@ fn test_extend() { #[test] fn test_is_send_sync() { - let data = ArrayVec::<[Vec; 5]>::new(); + let data = ArrayVec::, 5>::new(); &data as &dyn Send; &data as &dyn Sync; } #[test] fn test_compact_size() { - // Future rust will kill these drop flags! - // 4 elements size + 1 len + 1 enum tag + [1 drop flag] - type ByteArray = ArrayVec<[u8; 4]>; + // 4 bytes + padding + length + type ByteArray = ArrayVec; println!("{}", mem::size_of::()); - assert!(mem::size_of::() <= 8); + assert!(mem::size_of::() <= 2 * mem::size_of::()); - // 1 enum tag + 1 drop flag - type EmptyArray = ArrayVec<[u8; 0]>; + // just length + type EmptyArray = ArrayVec; println!("{}", mem::size_of::()); - assert!(mem::size_of::() <= 2); + assert!(mem::size_of::() <= mem::size_of::()); - // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding - type QuadArray = ArrayVec<[u32; 3]>; + // 3 elements + padding + length + type QuadArray = ArrayVec; println!("{}", mem::size_of::()); - assert!(mem::size_of::() <= 24); + assert!(mem::size_of::() <= 4 * 4 + mem::size_of::()); } #[test] fn test_still_works_with_option_arrayvec() { - type RefArray = ArrayVec<[&'static i32; 2]>; + type RefArray = ArrayVec<&'static i32, 2>; let array = Some(RefArray::new()); assert!(array.is_some()); println!("{:?}", array); @@ -308,7 +307,7 @@ fn test_drain() { v.extend(0..); v.drain(1..4); assert_eq!(&v[..], &[0, 4, 5, 6, 7]); - let u: ArrayVec<[_; 3]> = v.drain(1..4).rev().collect(); + let u: ArrayVec<_, 3> = v.drain(1..4).rev().collect(); assert_eq!(&u[..], &[6, 5, 4]); assert_eq!(&v[..], &[0, 7]); v.drain(..); @@ -324,7 +323,7 @@ fn test_drain_range_inclusive() { v.extend(0..); v.drain(1..=4); assert_eq!(&v[..], &[0, 5, 6, 7]); - let u: ArrayVec<[_; 3]> = v.drain(1..=2).rev().collect(); + let u: ArrayVec<_, 3> = v.drain(1..=2).rev().collect(); assert_eq!(&u[..], &[6, 5]); assert_eq!(&v[..], &[0, 7]); v.drain(..); @@ -374,7 +373,7 @@ fn test_drop_panic() { } } - let mut array = ArrayVec::<[DropPanic; 1]>::new(); + let mut array = ArrayVec::::new(); array.push(DropPanic); } @@ -389,7 +388,7 @@ fn test_drop_panic_into_iter() { } } - let mut array = ArrayVec::<[DropPanic; 1]>::new(); + let mut array = ArrayVec::::new(); array.push(DropPanic); array.into_iter(); } @@ -399,7 +398,7 @@ fn test_insert() { let mut v = ArrayVec::from([]); assert_matches!(v.try_push(1), Err(_)); - let mut v = ArrayVec::<[_; 3]>::new(); + let mut v = ArrayVec::<_, 3>::new(); v.insert(0, 0); v.insert(1, 1); //let ret1 = v.try_insert(3, 3); @@ -428,7 +427,7 @@ fn test_into_inner_1() { #[test] fn test_into_inner_2() { - let mut v = ArrayVec::<[String; 4]>::new(); + let mut v = ArrayVec::::new(); v.push("a".into()); v.push("b".into()); v.push("c".into()); @@ -438,7 +437,7 @@ fn test_into_inner_2() { #[test] fn test_into_inner_3_() { - let mut v = ArrayVec::<[i32; 4]>::new(); + let mut v = ArrayVec::::new(); v.extend(1..); assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); } @@ -447,7 +446,7 @@ fn test_into_inner_3_() { #[test] fn test_write() { use std::io::Write; - let mut v = ArrayVec::<[_; 8]>::new(); + let mut v = ArrayVec::<_, 8>::new(); write!(&mut v, "\x01\x02\x03").unwrap(); assert_eq!(&v[..], &[1, 2, 3]); let r = v.write(&[9; 16]).unwrap(); @@ -457,16 +456,16 @@ fn test_write() { #[test] fn array_clone_from() { - let mut v = ArrayVec::<[_; 4]>::new(); + let mut v = ArrayVec::<_, 4>::new(); v.push(vec![1, 2]); v.push(vec![3, 4, 5]); v.push(vec![6]); let reference = v.to_vec(); - let mut u = ArrayVec::<[_; 4]>::new(); + let mut u = ArrayVec::<_, 4>::new(); u.clone_from(&v); assert_eq!(&u, &reference[..]); - let mut t = ArrayVec::<[_; 4]>::new(); + let mut t = ArrayVec::<_, 4>::new(); t.push(vec![97]); t.push(vec![]); t.push(vec![5, 6, 2]); @@ -484,7 +483,7 @@ fn test_string() { use std::error::Error; let text = "hello world"; - let mut s = ArrayString::<[_; 16]>::new(); + let mut s = ArrayString::<16>::new(); s.try_push_str(text).unwrap(); assert_eq!(&s, text); assert_eq!(text, &s); @@ -494,7 +493,7 @@ fn test_string() { map.insert(s, 1); assert_eq!(map[text], 1); - let mut t = ArrayString::<[_; 2]>::new(); + let mut t = ArrayString::<2>::new(); assert!(t.try_push_str(text).is_err()); assert_eq!(&t, ""); @@ -505,7 +504,7 @@ fn test_string() { // Test Error trait / try let t = || -> Result<(), Box> { - let mut t = ArrayString::<[_; 2]>::new(); + let mut t = ArrayString::<2>::new(); t.try_push_str(text)?; Ok(()) }(); @@ -516,7 +515,7 @@ fn test_string() { fn test_string_from() { let text = "hello world"; // Test `from` constructor - let u = ArrayString::<[_; 11]>::from(text).unwrap(); + let u = ArrayString::<11>::from(text).unwrap(); assert_eq!(&u, text); assert_eq!(u.len(), text.len()); } @@ -524,7 +523,7 @@ fn test_string_from() { #[test] fn test_string_parse_from_str() { let text = "hello world"; - let u: ArrayString<[_; 11]> = text.parse().unwrap(); + let u: ArrayString<11> = text.parse().unwrap(); assert_eq!(&u, text); assert_eq!(u.len(), text.len()); } @@ -540,9 +539,9 @@ fn test_string_from_bytes() { #[test] fn test_string_clone() { let text = "hi"; - let mut s = ArrayString::<[_; 4]>::new(); + let mut s = ArrayString::<4>::new(); s.push_str("abcd"); - let t = ArrayString::<[_; 4]>::from(text).unwrap(); + let t = ArrayString::<4>::from(text).unwrap(); s.clone_from(&t); assert_eq!(&t, &s); } @@ -550,7 +549,7 @@ fn test_string_clone() { #[test] fn test_string_push() { let text = "abcαβγ"; - let mut s = ArrayString::<[_; 8]>::new(); + let mut s = ArrayString::<8>::new(); for c in text.chars() { if let Err(_) = s.try_push(c) { break; @@ -565,7 +564,7 @@ fn test_string_push() { #[test] fn test_insert_at_length() { - let mut v = ArrayVec::<[_; 8]>::new(); + let mut v = ArrayVec::<_, 8>::new(); let result1 = v.try_insert(0, "a"); let result2 = v.try_insert(1, "b"); assert!(result1.is_ok() && result2.is_ok()); @@ -575,7 +574,7 @@ fn test_insert_at_length() { #[should_panic] #[test] fn test_insert_out_of_bounds() { - let mut v = ArrayVec::<[_; 8]>::new(); + let mut v = ArrayVec::<_, 8>::new(); let _ = v.try_insert(1, "test"); } @@ -608,7 +607,7 @@ fn test_drop_in_insert() { flag.set(0); { - let mut array = ArrayVec::<[_; 2]>::new(); + let mut array = ArrayVec::<_, 2>::new(); array.push(Bump(flag)); array.insert(0, Bump(flag)); assert_eq!(flag.get(), 0); @@ -623,7 +622,7 @@ fn test_drop_in_insert() { #[test] fn test_pop_at() { - let mut v = ArrayVec::<[String; 4]>::new(); + let mut v = ArrayVec::::new(); let s = String::from; v.push(s("a")); v.push(s("b")); @@ -646,9 +645,9 @@ fn test_sizes() { #[test] fn test_default() { use std::net; - let s: ArrayString<[u8; 4]> = Default::default(); + let s: ArrayString<4> = Default::default(); // Something without `Default` implementation. - let v: ArrayVec<[net::TcpStream; 4]> = Default::default(); + let v: ArrayVec = Default::default(); assert_eq!(s.len(), 0); assert_eq!(v.len(), 0); } @@ -673,14 +672,14 @@ fn test_extend_zst() { #[derive(Copy, Clone, PartialEq, Debug)] struct Z; // Zero sized type - let mut array: ArrayVec<[_; 5]> = range.by_ref().map(|_| Z).collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 5]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().map(|_| Z)); assert_eq!(range.next(), Some(6)); - let mut array: ArrayVec<[_; 10]> = (0..3).map(|_| Z).collect(); + let mut array: ArrayVec<_, 10> = (0..3).map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 3]); array.extend((3..5).map(|_| Z)); assert_eq!(&array[..], &[Z; 5]); @@ -690,6 +689,6 @@ fn test_extend_zst() { #[test] fn test_try_from_argument() { use core::convert::TryFrom; - let v = ArrayString::<[u8; 16]>::try_from(format_args!("Hello {}", 123)).unwrap(); + let v = ArrayString::<16>::try_from(format_args!("Hello {}", 123)).unwrap(); assert_eq!(&v, "Hello 123"); }