From a2b2efd379b8a357aba1cdc2206095f351a241fc Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 16 Dec 2020 21:47:04 +0100 Subject: [PATCH 01/12] Add ArrayvecImpl, base implementation of ArrayVec --- src/arrayvec_impl.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 75 insertions(+) create mode 100644 src/arrayvec_impl.rs diff --git a/src/arrayvec_impl.rs b/src/arrayvec_impl.rs new file mode 100644 index 00000000..3772fda2 --- /dev/null +++ b/src/arrayvec_impl.rs @@ -0,0 +1,74 @@ +use std::ptr; + +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]; + + /// Return a mutable slice containing all elements of the vector. + fn as_mut_slice(&mut self) -> &mut [Self::Item]; + + /// 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 { + if new_len < self.len() { + let tail: *mut [_] = &mut self.as_mut_slice()[new_len..]; + self.set_len(new_len); + ptr::drop_in_place(tail); + } + } + } +} + diff --git a/src/lib.rs b/src/lib.rs index d3bed603..2d21aa26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,6 +41,7 @@ use crate::maybe_uninit::MaybeUninit; use serde::{Serialize, Deserialize, Serializer, Deserializer}; mod array; +mod arrayvec_impl; mod arrayvec; mod array_string; mod char; From 630b81b8486ac81663da319afba5fd4261605b6b Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 16 Dec 2020 21:47:50 +0100 Subject: [PATCH 02/12] Use ArrayVecImpl in ArrayVec --- src/arrayvec.rs | 66 +++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 1f168f9f..a2450b0a 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -23,6 +23,7 @@ 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. /// @@ -159,7 +160,7 @@ impl ArrayVec { /// assert_eq!(&array[..], &[1, 2]); /// ``` pub fn push(&mut self, element: A::Item) { - self.try_push(element).unwrap() + ArrayVecImpl::push(self, element) } /// Push `element` to the end of the vector. @@ -185,14 +186,7 @@ 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)) - } + ArrayVecImpl::try_push(self, element) } @@ -218,10 +212,7 @@ 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); + ArrayVecImpl::push_unchecked(self, element) } /// Get pointer to where element at `index` would be @@ -314,14 +305,7 @@ impl ArrayVec { /// 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))) - } + ArrayVecImpl::pop(self) } /// Remove the element at `index` and swap the last element into its place. @@ -438,18 +422,12 @@ impl ArrayVec { /// 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); - } - } + ArrayVecImpl::truncate(self, new_len) } /// Remove all elements in the vector. pub fn clear(&mut self) { - self.truncate(0) + ArrayVecImpl::clear(self) } /// Retains only the elements specified by the predicate. @@ -664,6 +642,36 @@ impl DerefMut for ArrayVec { } } +impl ArrayVecImpl for ArrayVec { + type Item = A::Item; + + const CAPACITY: usize = A::CAPACITY; + + fn len(&self) -> usize { self.len() } + unsafe fn set_len(&mut self, length: usize) { self.set_len(length) } + + /// Return a slice containing all elements of the vector. + fn as_slice(&self) -> &[A::Item] { + self + } + + /// Return a mutable slice containing all elements of the vector. + fn as_mut_slice(&mut self) -> &mut [A::Item] { + self + } + + /// Return a raw pointer to the vector's buffer. + fn as_ptr(&self) -> *const A::Item { + self.xs.ptr() + } + + /// Return a raw mutable pointer to the vector's buffer. + fn as_mut_ptr(&mut self) -> *mut A::Item { + self.xs.ptr_mut() + } +} + + /// Create an `ArrayVec` from an array. /// /// ``` From 02ab4dc79663eb6f3b4e49a7df0951ef9c0e18d5 Mon Sep 17 00:00:00 2001 From: bluss Date: Wed, 16 Dec 2020 21:48:34 +0100 Subject: [PATCH 03/12] FEAT: Add new const generics version of ArrayVec (first draft) --- src/arrayvec.rs | 385 +++++++++++++++++++++---------------------- src/arrayvec_impl.rs | 20 ++- 2 files changed, 203 insertions(+), 202 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index a2450b0a..0fb3c754 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -14,13 +14,15 @@ use std::fmt; #[cfg(feature="std")] use std::io; -use crate::maybe_uninit::MaybeUninit; +use std::mem::ManuallyDrop; +use std::mem::MaybeUninit; + +//use crate::maybe_uninit::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; @@ -37,12 +39,13 @@ use crate::arrayvec_impl::ArrayVecImpl; /// 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(); @@ -57,7 +60,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. @@ -72,16 +78,16 @@ impl ArrayVec { /// 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 } } } @@ -95,7 +101,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. /// @@ -118,7 +124,7 @@ 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. /// @@ -159,7 +165,7 @@ impl ArrayVec { /// /// assert_eq!(&array[..], &[1, 2]); /// ``` - pub fn push(&mut self, element: A::Item) { + pub fn push(&mut self, element: T) { ArrayVecImpl::push(self, element) } @@ -185,11 +191,10 @@ impl ArrayVec { /// /// assert!(overflow.is_err()); /// ``` - pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError> { + 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 @@ -211,13 +216,38 @@ impl ArrayVec { /// /// assert_eq!(&array[..], &[1, 2]); /// ``` - pub unsafe fn push_unchecked(&mut self, element: A::Item) { + 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`. @@ -240,7 +270,7 @@ impl ArrayVec { /// 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() } @@ -264,7 +294,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()) } @@ -304,7 +334,7 @@ impl ArrayVec { /// assert_eq!(array.pop(), Some(1)); /// assert_eq!(array.pop(), None); /// ``` - pub fn pop(&mut self) -> Option { + pub fn pop(&mut self) -> Option { ArrayVecImpl::pop(self) } @@ -327,7 +357,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()) @@ -351,7 +381,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; @@ -375,7 +405,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()) @@ -398,7 +428,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 { @@ -406,30 +436,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) { - ArrayVecImpl::truncate(self, new_len) - } - - /// Remove all elements in the vector. - pub fn clear(&mut self) { - ArrayVecImpl::clear(self) - } - /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&mut e)` returns false. @@ -444,7 +450,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; @@ -494,8 +500,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(())); @@ -505,7 +511,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); } @@ -530,7 +536,7 @@ impl ArrayVec { /// 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 @@ -557,7 +563,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(); @@ -582,12 +588,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) } @@ -602,72 +608,58 @@ 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() - } -} - -impl Deref for ArrayVec { - type Target = [A::Item]; - #[inline] - fn deref(&self) -> &[A::Item] { - unsafe { - slice::from_raw_parts(self.xs.ptr(), self.len()) - } - } -} - -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) - } + pub fn as_mut_ptr(&mut self) -> *mut T { + ArrayVecImpl::as_mut_ptr(self) } } -impl ArrayVecImpl for ArrayVec { - type Item = A::Item; - - const CAPACITY: usize = A::CAPACITY; +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) { self.set_len(length) } - /// Return a slice containing all elements of the vector. - fn as_slice(&self) -> &[A::Item] { - self + unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= CAP); + self.len = length; } - /// Return a mutable slice containing all elements of the vector. - fn as_mut_slice(&mut self) -> &mut [A::Item] { - self + fn as_ptr(&self) -> *const Self::Item { + self.xs.as_ptr() as _ } - /// Return a raw pointer to the vector's buffer. - fn as_ptr(&self) -> *const A::Item { - self.xs.ptr() + fn as_mut_ptr(&mut self) -> *mut Self::Item { + self.xs.as_mut_ptr() as _ } +} - /// Return a raw mutable pointer to the vector's buffer. - fn as_mut_ptr(&mut self) -> *mut A::Item { - self.xs.ptr_mut() +impl Deref for ArrayVec { + type Target = [T]; + #[inline] + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl DerefMut for ArrayVec { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() } } @@ -681,9 +673,16 @@ impl ArrayVecImpl 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 } } @@ -699,14 +698,13 @@ impl From for ArrayVec { /// 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(); @@ -728,9 +726,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() } } @@ -745,9 +743,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() } } @@ -762,44 +760,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 { +impl IntoIterator for ArrayVec { + type Item = T; + type IntoIter = IntoIter; + fn into_iter(self) -> IntoIter { IntoIter { index: Index::from(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 { @@ -812,12 +810,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); @@ -829,51 +827,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| @@ -888,8 +880,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| @@ -900,11 +891,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. @@ -948,8 +937,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(); @@ -1003,16 +992,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() @@ -1035,61 +1024,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) } @@ -1110,8 +1099,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) } } @@ -1120,7 +1109,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]); @@ -1132,7 +1121,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 { @@ -1142,17 +1131,17 @@ 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) @@ -1173,6 +1162,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 index 3772fda2..6c09834a 100644 --- a/src/arrayvec_impl.rs +++ b/src/arrayvec_impl.rs @@ -1,4 +1,5 @@ use std::ptr; +use std::slice; use crate::CapacityError; @@ -13,10 +14,20 @@ pub(crate) trait ArrayVecImpl { unsafe fn set_len(&mut self, new_len: usize); /// Return a slice containing all elements of the vector. - fn as_slice(&self) -> &[Self::Item]; + 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]; + 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; @@ -63,9 +74,10 @@ pub(crate) trait ArrayVecImpl { fn truncate(&mut self, new_len: usize) { unsafe { - if new_len < self.len() { - let tail: *mut [_] = &mut self.as_mut_slice()[new_len..]; + 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); } } From 5502324b6f7b9ce374ee106324ab8d59f62fff04 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 17:12:28 +0100 Subject: [PATCH 04/12] TEST: Fix arrayvec tests for const gen Just search/replace for syntax [T; N] -> T, N and it works. --- src/arrayvec.rs | 24 ++++++++-------- tests/tests.rs | 76 ++++++++++++++++++++++++------------------------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 0fb3c754..680020e7 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -71,7 +71,7 @@ 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]); @@ -131,7 +131,7 @@ impl ArrayVec { /// ``` /// 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()); @@ -158,7 +158,7 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// array.push(1); /// array.push(2); @@ -177,7 +177,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); @@ -205,7 +205,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 { @@ -263,7 +263,7 @@ 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"); @@ -286,7 +286,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()); @@ -327,7 +327,7 @@ impl ArrayVec { /// ``` /// use arrayvec::ArrayVec; /// - /// let mut array = ArrayVec::<[_; 2]>::new(); + /// let mut array = ArrayVec::<_, 2>::new(); /// /// array.push(1); /// @@ -487,7 +487,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]); @@ -532,7 +532,7 @@ 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]); /// ``` @@ -678,9 +678,9 @@ impl From<[T; CAP]> for ArrayVec { 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 } @@ -694,7 +694,7 @@ impl From<[T; CAP]> 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); /// ``` diff --git a/tests/tests.rs b/tests/tests.rs index 593b5e41..d1bae4fd 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,7 +266,7 @@ 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; } @@ -275,24 +275,24 @@ fn test_is_send_sync() { 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]>; + type ByteArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 8); // 1 enum tag + 1 drop flag - type EmptyArray = ArrayVec<[u8; 0]>; + type EmptyArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 2); // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding - type QuadArray = ArrayVec<[u32; 3]>; + type QuadArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 24); } #[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 +308,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 +324,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 +374,7 @@ fn test_drop_panic() { } } - let mut array = ArrayVec::<[DropPanic; 1]>::new(); + let mut array = ArrayVec::::new(); array.push(DropPanic); } @@ -389,7 +389,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 +399,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 +428,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 +438,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 +447,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 +457,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]); @@ -565,7 +565,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 +575,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 +608,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 +623,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")); @@ -648,7 +648,7 @@ fn test_default() { use std::net; let s: ArrayString<[u8; 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 +673,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]); From 18877f243a6c131be4f16ecf7594f7fc6471db56 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 17:21:35 +0100 Subject: [PATCH 05/12] TEST: Fix size assertion test for const gen With const generics we can't avoid the usize (or other type) length field. --- tests/tests.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index d1bae4fd..46fb575a 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -273,21 +273,20 @@ fn test_is_send_sync() { #[test] fn test_compact_size() { - // Future rust will kill these drop flags! - // 4 elements size + 1 len + 1 enum tag + [1 drop flag] + // 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 + // 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 + // 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] From fc9c4068f5dbfbc7fb5c4361af421a4e9452532f Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 17:24:05 +0100 Subject: [PATCH 06/12] MAINT: Update ci for const gen --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0aeb6e6..13f116aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,12 +13,11 @@ env: jobs: tests: runs-on: ubuntu-latest + continue-on-error: true strategy: matrix: include: - - rust: 1.36.0 # MSRV - features: serde - - rust: stable + - rust: 1.51.0 # MSRV features: serde - rust: stable features: array-sizes-33-128 array-sizes-129-255 From c9b095f26328e08e4f9dae34897b39ea6f4145a4 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 17:31:27 +0100 Subject: [PATCH 07/12] FEAT: Port ArrayString to const generics --- src/array_string.rs | 193 +++++++++++++++++++------------------------- src/arrayvec.rs | 3 - src/lib.rs | 3 - src/maybe_uninit.rs | 44 ---------- 4 files changed, 84 insertions(+), 159 deletions(-) delete mode 100644 src/maybe_uninit.rs diff --git a/src/array_string.rs b/src/array_string.rs index 48139b21..d8dc6acf 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 680020e7..d58ebc2f 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -17,9 +17,6 @@ use std::io; use std::mem::ManuallyDrop; use std::mem::MaybeUninit; -//use crate::maybe_uninit::MaybeUninit; - - #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; diff --git a/src/lib.rs b/src/lib.rs index 2d21aa26..cfd15154 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,9 +34,6 @@ 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}; 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 - } -} From 6daae9ae68029628db27e6cafe44bb83e7377c28 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 17:49:11 +0100 Subject: [PATCH 08/12] FIX: Fix serde feature for const gen --- src/array_string.rs | 6 +++--- src/arrayvec.rs | 6 +++--- src/lib.rs | 3 --- tests/serde.rs | 12 ++++++------ tests/tests.rs | 20 ++++++++++---------- 5 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index d8dc6acf..c642e2bd 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -533,10 +533,10 @@ impl<'de, const CAP: usize> Deserialize<'de> for ArrayString use serde::de::{self, Visitor}; use std::marker::PhantomData; - struct ArrayStringVisitor(PhantomData([u8; CAP])); + struct ArrayStringVisitor(PhantomData<[u8; CAP]>); - impl<'de, const CAP: usize> 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", CAP) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index d58ebc2f..97a46ae1 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1141,17 +1141,17 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for 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)); } } diff --git a/src/lib.rs b/src/lib.rs index cfd15154..85a04a27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,9 +34,6 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -#[cfg(feature="serde")] -use serde::{Serialize, Deserialize, Serializer, Deserializer}; - mod array; mod arrayvec_impl; mod arrayvec; 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 46fb575a..676cd7cd 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -483,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); @@ -493,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, ""); @@ -504,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(()) }(); @@ -515,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()); } @@ -523,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()); } @@ -539,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); } @@ -549,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; @@ -645,7 +645,7 @@ 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 = Default::default(); assert_eq!(s.len(), 0); @@ -689,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"); } From f2e9378fd6e069a5a23275f9e1aabddfbdce64ab Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 18:07:25 +0100 Subject: [PATCH 09/12] FIX: Fix unstable-const-fn feature --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 85a04a27..f9553897 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,7 @@ //! #![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; From c751c2204f1b524d37a907b59f1b58049c56e463 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 18:10:14 +0100 Subject: [PATCH 10/12] Remove old Array and Index traits --- .github/workflows/ci.yml | 2 +- Cargo.toml | 3 - src/array.rs | 151 --------------------------------------- src/arrayvec.rs | 9 ++- src/lib.rs | 5 -- 5 files changed, 5 insertions(+), 165 deletions(-) delete mode 100644 src/array.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13f116aa..ca278e84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: - rust: 1.51.0 # MSRV 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/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/arrayvec.rs b/src/arrayvec.rs index 97a46ae1..c7c4a2ce 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -21,7 +21,6 @@ use std::mem::MaybeUninit; use serde::{Serialize, Deserialize, Serializer, Deserializer}; use crate::errors::CapacityError; -use crate::array::Index; use crate::arrayvec_impl::ArrayVecImpl; /// A vector with a fixed capacity. @@ -476,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`. @@ -569,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 { @@ -761,7 +760,7 @@ impl IntoIterator for ArrayVec { type Item = T; type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { - IntoIter { index: Index::from(0), v: self, } + IntoIter { index: 0, v: self, } } } @@ -949,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(); diff --git a/src/lib.rs b/src/lib.rs index f9553897..0d7f21ed 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 @@ -34,14 +31,12 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -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; From d273861cde87ac91a18e2a169512443b848e7585 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 18:19:31 +0100 Subject: [PATCH 11/12] DOC: Update MSRV doc to Rust 1.51 --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0d7f21ed..e0a58173 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ //! //! ## 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)] From 182097035d6417c0d27f96c0434167341ca2bd82 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 18:25:56 +0100 Subject: [PATCH 12/12] TEST: Update benches for const gen --- benches/arraystring.rs | 12 ++++++------ benches/extend.rs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) 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();