From a056801e077dba5252aaeb089958673c6856d867 Mon Sep 17 00:00:00 2001 From: JakkuSakura Date: Tue, 19 Dec 2023 10:48:49 +0900 Subject: [PATCH 1/7] feat: put len before xs --- src/array_string.rs | 3 ++- src/arrayvec.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index 90cfc09..7f6e299 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -31,10 +31,11 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer}; /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] +#[repr(C)] pub struct ArrayString { // the `len` first elements of the array are initialized - xs: [MaybeUninit; CAP], len: LenUint, + xs: [MaybeUninit; CAP], } impl Default for ArrayString diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 37e151a..f7fcbd2 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -39,10 +39,11 @@ use crate::utils::MakeMaybeUninit; /// /// It offers a simple API but also dereferences to a slice, so that the full slice API is /// available. The ArrayVec can be converted into a by value iterator. +#[repr(C)] pub struct ArrayVec { + len: LenUint, // the `len` first elements of the array are initialized xs: [MaybeUninit; CAP], - len: LenUint, } impl Drop for ArrayVec { From 57e1557dfa26258be9c3badb8f2ab3d72cb82541 Mon Sep 17 00:00:00 2001 From: JakkuSakura Date: Thu, 21 Dec 2023 11:20:07 +0900 Subject: [PATCH 2/7] feat: make LenUint generic --- src/array_string.rs | 124 ++++++++++++++-------------- src/arrayvec.rs | 192 ++++++++++++++++++++++---------------------- src/lib.rs | 48 ++++++++--- src/utils.rs | 1 - tests/tests.rs | 132 +++++++++++++++--------------- 5 files changed, 257 insertions(+), 240 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index 7f6e299..1a7c790 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -11,12 +11,12 @@ use std::str; use std::str::FromStr; use std::str::Utf8Error; -use crate::CapacityError; +use crate::{CapacityError, DefaultLenUint}; use crate::LenUint; use crate::char::encode_utf8; use crate::utils::MakeMaybeUninit; -#[cfg(feature="serde")] +#[cfg(feature = "serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; @@ -32,21 +32,21 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer}; /// if needed. #[derive(Copy)] #[repr(C)] -pub struct ArrayString { +pub struct ArrayString { // the `len` first elements of the array are initialized - len: LenUint, + len: LenType, xs: [MaybeUninit; CAP], } -impl Default for ArrayString +impl Default for ArrayString { /// Return an empty `ArrayString` - fn default() -> ArrayString { + fn default() -> Self { ArrayString::new() } } -impl ArrayString +impl ArrayString { /// Create a new empty `ArrayString`. /// @@ -60,11 +60,9 @@ impl ArrayString /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` - pub fn new() -> ArrayString { - assert_capacity_limit!(CAP); - unsafe { - ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } - } + pub fn new() -> Self { + assert_capacity_limit!(LenType, CAP); + ArrayString { len: LenType::from_usize(0), xs: MakeMaybeUninit::ARRAY } } /// Create a new empty `ArrayString` (const fn). @@ -74,20 +72,20 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); + /// const ARRAY: ArrayString<1024> = ArrayString::new_const(); /// ``` - pub const fn new_const() -> ArrayString { - assert_capacity_limit_const!(CAP); - ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 } + pub const fn new_const() -> Self { + assert_capacity_limit_const!(LenType, CAP); + ArrayString { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } /// Return the length of the string. #[inline] - pub const fn len(&self) -> usize { self.len as usize } + pub fn len(&self) -> usize { LenType::to_usize(self.len) } /// Returns whether the string is empty. #[inline] - pub const fn is_empty(&self) -> bool { self.len() == 0 } + pub fn is_empty(&self) -> bool { self.len == LenType::ZERO } /// Create a new `ArrayString` from a `str`. /// @@ -141,13 +139,13 @@ impl ArrayString /// ``` #[inline] pub fn zero_filled() -> Self { - assert_capacity_limit!(CAP); + assert_capacity_limit!(LenType, CAP); // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and // `zeroed` fully fills the array with nulls. unsafe { ArrayString { xs: MaybeUninit::zeroed().assume_init(), - len: CAP as _ + len: LenType::from_usize(CAP), } } } @@ -173,7 +171,7 @@ impl ArrayString /// string.push_str("A"); /// assert!(string.is_full()); /// ``` - pub const fn is_full(&self) -> bool { self.len() == self.capacity() } + pub fn is_full(&self) -> bool { self.len() == self.capacity() } /// Returns the capacity left in the `ArrayString`. /// @@ -184,7 +182,7 @@ impl ArrayString /// string.pop(); /// assert_eq!(string.remaining_capacity(), 1); /// ``` - pub const fn remaining_capacity(&self) -> usize { + pub fn remaining_capacity(&self) -> usize { self.capacity() - self.len() } @@ -299,7 +297,7 @@ impl ArrayString /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); @@ -339,7 +337,7 @@ impl ArrayString pub fn truncate(&mut self, new_len: usize) { if new_len <= self.len() { assert!(self.is_char_boundary(new_len)); - unsafe { + unsafe { // In libstd truncate is called on the underlying vector, // which in turns drops each element. // As we know we don't have to worry about Drop, @@ -359,7 +357,7 @@ impl ArrayString /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); @@ -402,7 +400,7 @@ impl ArrayString pub unsafe fn set_len(&mut self, length: usize) { // type invariant that capacity always fits in LenUint debug_assert!(length <= self.capacity()); - self.len = length as LenUint; + self.len = LenUint::from_usize(length); } /// Return a string slice of the whole `ArrayString`. @@ -424,7 +422,7 @@ impl ArrayString } } -impl Deref for ArrayString +impl Deref for ArrayString { type Target = str; #[inline] @@ -436,7 +434,7 @@ impl Deref for ArrayString } } -impl DerefMut for ArrayString +impl DerefMut for ArrayString { #[inline] fn deref_mut(&mut self) -> &mut str { @@ -448,64 +446,64 @@ impl DerefMut for ArrayString } } -impl PartialEq for ArrayString +impl PartialEq for ArrayString { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } -impl PartialEq for ArrayString +impl PartialEq for ArrayString { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } -impl PartialEq> for str +impl PartialEq> for str { - fn eq(&self, rhs: &ArrayString) -> bool { + fn eq(&self, rhs: &ArrayString) -> bool { self == &**rhs } } -impl Eq for ArrayString -{ } +impl Eq for ArrayString +{} -impl Hash for ArrayString +impl Hash for ArrayString { fn hash(&self, h: &mut H) { (**self).hash(h) } } -impl Borrow for ArrayString +impl Borrow for ArrayString { fn borrow(&self) -> &str { self } } -impl BorrowMut for ArrayString +impl BorrowMut for ArrayString { fn borrow_mut(&mut self) -> &mut str { self } } -impl AsRef for ArrayString +impl AsRef for ArrayString { fn as_ref(&self) -> &str { self } } -impl fmt::Debug for ArrayString +impl fmt::Debug for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl fmt::Display for ArrayString +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 +impl fmt::Write for ArrayString { fn write_char(&mut self, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error) @@ -516,9 +514,9 @@ impl fmt::Write for ArrayString } } -impl Clone for ArrayString +impl Clone for ArrayString { - fn clone(&self) -> ArrayString { + fn clone(&self) -> ArrayString { *self } fn clone_from(&mut self, rhs: &Self) { @@ -528,7 +526,7 @@ impl Clone for ArrayString } } -impl PartialOrd for ArrayString +impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &Self) -> Option { (**self).partial_cmp(&**rhs) @@ -539,7 +537,7 @@ impl PartialOrd for ArrayString fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } } -impl PartialOrd for ArrayString +impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &str) -> Option { (**self).partial_cmp(rhs) @@ -550,25 +548,25 @@ impl PartialOrd for ArrayString fn ge(&self, rhs: &str) -> bool { &**self >= rhs } } -impl PartialOrd> for str +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 +impl Ord for ArrayString { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } -impl FromStr for ArrayString +impl FromStr for ArrayString { type Err = CapacityError; @@ -577,9 +575,9 @@ impl FromStr for ArrayString } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl Serialize for ArrayString +impl Serialize for ArrayString { fn serialize(&self, serializer: S) -> Result where S: Serializer @@ -588,9 +586,9 @@ impl Serialize for ArrayString } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl<'de, const CAP: usize> Deserialize<'de> for ArrayString +impl<'de, const CAP: usize, LenType: LenUint> Deserialize<'de> for ArrayString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> @@ -598,10 +596,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], LenType)>); - impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor { - type Value = ArrayString; + impl<'de, const CAP: usize, LenType: LenUint> 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) @@ -626,7 +624,7 @@ impl<'de, const CAP: usize> Deserialize<'de> for ArrayString } } -impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString +impl<'a, const CAP: usize, LenType: LenUint> TryFrom<&'a str> for ArrayString { type Error = CapacityError<&'a str>; @@ -637,7 +635,7 @@ impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString } } -impl<'a, const CAP: usize> TryFrom> for ArrayString +impl<'a, const CAP: usize, LenType: LenUint> TryFrom> for ArrayString { type Error = CapacityError; @@ -664,7 +662,7 @@ impl<'a, const CAP: usize> TryFrom> for ArrayString /// unsafe { string.set_len(string.capacity()) }; /// assert_eq!(&*string, "\0\0\0\0\0\0"); /// ``` -impl zeroize::Zeroize for ArrayString { +impl zeroize::Zeroize for ArrayString { fn zeroize(&mut self) { // There are no elements to drop self.clear(); diff --git a/src/arrayvec.rs b/src/arrayvec.rs index f7fcbd2..b101025 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1,4 +1,3 @@ - use std::cmp; use std::iter; use std::mem; @@ -11,16 +10,16 @@ use std::borrow::{Borrow, BorrowMut}; use std::hash::{Hash, Hasher}; use std::fmt; -#[cfg(feature="std")] +#[cfg(feature = "std")] use std::io; use std::mem::ManuallyDrop; use std::mem::MaybeUninit; -#[cfg(feature="serde")] +#[cfg(feature = "serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use crate::LenUint; +use crate::{DefaultLenUint, LenUint}; use crate::errors::CapacityError; use crate::arrayvec_impl::ArrayVecImpl; use crate::utils::MakeMaybeUninit; @@ -40,13 +39,13 @@ use crate::utils::MakeMaybeUninit; /// It offers a simple API but also dereferences to a slice, so that the full slice API is /// available. The ArrayVec can be converted into a by value iterator. #[repr(C)] -pub struct ArrayVec { - len: LenUint, +pub struct ArrayVec { + len: LenType, // the `len` first elements of the array are initialized xs: [MaybeUninit; CAP], } -impl Drop for ArrayVec { +impl Drop for ArrayVec { fn drop(&mut self) { self.clear(); @@ -61,7 +60,7 @@ macro_rules! panic_oob { } } -impl ArrayVec { +impl ArrayVec { /// Capacity const CAPACITY: usize = CAP; @@ -80,11 +79,9 @@ impl ArrayVec { /// ``` #[inline] #[track_caller] - pub fn new() -> ArrayVec { - assert_capacity_limit!(CAP); - unsafe { - ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } - } + pub fn new() -> Self { + assert_capacity_limit!(LenType, CAP); + ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } /// Create a new empty `ArrayVec` (const fn). @@ -96,9 +93,9 @@ impl ArrayVec { /// /// static ARRAY: ArrayVec = ArrayVec::new_const(); /// ``` - pub const fn new_const() -> ArrayVec { - assert_capacity_limit_const!(CAP); - ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 } + pub const fn new_const() -> Self { + assert_capacity_limit_const!(LenType, CAP); + ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } /// Return the number of elements in the `ArrayVec`. @@ -111,7 +108,7 @@ impl ArrayVec { /// assert_eq!(array.len(), 2); /// ``` #[inline(always)] - pub const fn len(&self) -> usize { self.len as usize } + pub fn len(&self) -> usize { self.len.to_usize() } /// Returns whether the `ArrayVec` is empty. /// @@ -123,7 +120,7 @@ impl ArrayVec { /// assert_eq!(array.is_empty(), true); /// ``` #[inline] - pub const fn is_empty(&self) -> bool { self.len() == 0 } + pub fn is_empty(&self) -> bool { self.len == LenType::ZERO } /// Return the capacity of the `ArrayVec`. /// @@ -146,7 +143,7 @@ impl ArrayVec { /// array.push(1); /// assert!(array.is_full()); /// ``` - pub const fn is_full(&self) -> bool { self.len() == self.capacity() } + pub fn is_full(&self) -> bool { self.len() == self.capacity() } /// Returns the capacity left in the `ArrayVec`. /// @@ -157,7 +154,7 @@ impl ArrayVec { /// array.pop(); /// assert_eq!(array.remaining_capacity(), 1); /// ``` - pub const fn remaining_capacity(&self) -> usize { + pub fn remaining_capacity(&self) -> usize { self.capacity() - self.len() } @@ -472,21 +469,21 @@ impl ArrayVec { let original_len = self.len(); unsafe { self.set_len(0) }; - struct BackshiftOnDrop<'a, T, const CAP: usize> { - v: &'a mut ArrayVec, + struct BackshiftOnDrop<'a, T, const CAP: usize, LenType: LenUint> { + v: &'a mut ArrayVec, processed_len: usize, deleted_cnt: usize, original_len: usize, } - impl Drop for BackshiftOnDrop<'_, T, CAP> { + impl Drop for BackshiftOnDrop<'_, T, CAP, LenType> { fn drop(&mut self) { if self.deleted_cnt > 0 { unsafe { ptr::copy( self.v.as_ptr().add(self.processed_len), self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), - self.original_len - self.processed_len + self.original_len - self.processed_len, ); } } @@ -499,9 +496,9 @@ impl ArrayVec { let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; #[inline(always)] - fn process_one bool, T, const CAP: usize, const DELETED: bool>( + fn process_one bool, T, const CAP: usize, const DELETED: bool, LenType: LenUint>( f: &mut F, - g: &mut BackshiftOnDrop<'_, T, CAP> + g: &mut BackshiftOnDrop<'_, T, CAP, LenType>, ) -> bool { let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) }; if !f(unsafe { &mut *cur }) { @@ -522,14 +519,14 @@ impl ArrayVec { // Stage 1: Nothing was deleted. while g.processed_len != original_len { - if !process_one::(&mut f, &mut g) { + if !process_one::(&mut f, &mut g) { break; } } // Stage 2: Some elements were deleted. while g.processed_len != original_len { - process_one::(&mut f, &mut g); + process_one::(&mut f, &mut g); } drop(g); @@ -545,7 +542,7 @@ impl ArrayVec { pub unsafe fn set_len(&mut self, length: usize) { // type invariant that capacity always fits in LenUint debug_assert!(length <= self.capacity()); - self.len = length as LenUint; + self.len = LenType::from_usize(length); } /// Copy all elements from the slice and append to the `ArrayVec`. @@ -602,7 +599,7 @@ impl ArrayVec { /// assert_eq!(&v1[..], &[3]); /// assert_eq!(&v2[..], &[1, 2]); /// ``` - pub fn drain(&mut self, range: R) -> Drain + pub fn drain(&mut self, range: R) -> Drain where R: RangeBounds { // Memory safety @@ -629,7 +626,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(); @@ -638,7 +635,8 @@ 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 = start as LenUint; + // safety: we just checked that the start is in bounds + self.len = LenType::from_usize(start); unsafe { Drain { @@ -682,7 +680,7 @@ impl ArrayVec { /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap()); /// assert!(v.is_empty()); /// ``` - pub fn take(&mut self) -> Self { + pub fn take(&mut self) -> Self { mem::replace(self, Self::new()) } @@ -707,15 +705,15 @@ impl ArrayVec { } } -impl ArrayVecImpl for ArrayVec { +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 as LenUint; + debug_assert!(length <= CAP, "length {} exceeds capacity {}", length, CAP); + self.len = LenType::from_usize(length); } fn as_ptr(&self) -> *const Self::Item { @@ -727,7 +725,7 @@ impl ArrayVecImpl for ArrayVec { } } -impl Deref for ArrayVec { +impl Deref for ArrayVec { type Target = [T]; #[inline] fn deref(&self) -> &Self::Target { @@ -735,7 +733,7 @@ impl Deref for ArrayVec { } } -impl DerefMut for ArrayVec { +impl DerefMut for ArrayVec { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() @@ -752,11 +750,11 @@ impl DerefMut for ArrayVec { /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 3); /// ``` -impl From<[T; CAP]> for ArrayVec { +impl From<[T; CAP]> for ArrayVec { #[track_caller] fn from(array: [T; CAP]) -> Self { let array = ManuallyDrop::new(array); - let mut vec = >::new(); + let mut vec = Self::new(); unsafe { (&*array as *const [T; CAP] as *const [MaybeUninit; CAP]) .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); @@ -778,7 +776,7 @@ impl From<[T; CAP]> for ArrayVec { /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 4); /// ``` -impl std::convert::TryFrom<&[T]> for ArrayVec +impl std::convert::TryFrom<&[T]> for ArrayVec where T: Clone, { type Error = CapacityError; @@ -806,7 +804,7 @@ impl std::convert::TryFrom<&[T]> for ArrayVec /// // ... /// } /// ``` -impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec { +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> IntoIterator for &'a ArrayVec { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } @@ -823,7 +821,7 @@ impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec { /// // ... /// } /// ``` -impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec { +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> 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() } @@ -840,11 +838,11 @@ impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec { /// // ... /// } /// ``` -impl IntoIterator for ArrayVec { +impl IntoIterator for ArrayVec { type Item = T; - type IntoIter = IntoIter; - fn into_iter(self) -> IntoIter { - IntoIter { index: 0, v: self, } + type IntoIter = IntoIter; + fn into_iter(self) -> Self::IntoIter { + IntoIter { index: 0, v: self } } } @@ -864,7 +862,7 @@ impl IntoIterator for ArrayVec { /// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) }; /// assert_eq!(data, [0, 0, 0]); /// ``` -impl zeroize::Zeroize for ArrayVec { +impl zeroize::Zeroize for ArrayVec { fn zeroize(&mut self) { // Zeroize all the contained elements. self.iter_mut().zeroize(); @@ -876,12 +874,12 @@ impl zeroize::Zeroize for ArrayVec { +pub struct IntoIter { index: usize, - v: ArrayVec, + v: ArrayVec, } -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { @@ -902,7 +900,7 @@ impl Iterator for IntoIter { } } -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { if self.index == self.v.len() { None @@ -916,9 +914,9 @@ 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; @@ -933,19 +931,19 @@ impl Drop for IntoIter { } } -impl Clone for IntoIter -where T: Clone, +impl Clone for IntoIter + where T: Clone, { - fn clone(&self) -> IntoIter { + fn clone(&self) -> Self { let mut v = ArrayVec::new(); v.extend_from_slice(&self.v[self.index..]); v.into_iter() } } -impl fmt::Debug for IntoIter -where - T: fmt::Debug, +impl fmt::Debug for IntoIter + where + T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -955,20 +953,21 @@ where } /// A draining iterator for `ArrayVec`. -pub struct Drain<'a, T: 'a, const CAP: usize> { +pub struct Drain<'a, T: 'a, const CAP: usize, LenType: LenUint> { /// Index of tail to preserve tail_start: usize, /// Length of tail tail_len: usize, /// Current remaining range to remove iter: slice::Iter<'a, T>, - vec: *mut ArrayVec, + vec: *mut ArrayVec, } -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> {} +unsafe impl<'a, T: Sync, const CAP: usize, LenType: LenUint> Sync for Drain<'a, T, CAP, LenType> {} + +unsafe impl<'a, T: Send, const CAP: usize, LenType: LenUint> Send for Drain<'a, T, CAP, LenType> {} -impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> Iterator for Drain<'a, T, CAP, LenType> { type Item = T; fn next(&mut self) -> Option { @@ -984,7 +983,7 @@ impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { } } -impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> DoubleEndedIterator for Drain<'a, T, CAP, LenType> { fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| @@ -995,14 +994,14 @@ impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> } } -impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {} +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> ExactSizeIterator for Drain<'a, T, CAP, LenType> {} -impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> { +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> Drop for Drain<'a, T, CAP, LenType> { fn drop(&mut self) { // len is currently 0 so panicking while dropping will not cause a double drop. // exhaust self first - while let Some(_) = self.next() { } + while let Some(_) = self.next() {} if self.tail_len > 0 { unsafe { @@ -1035,13 +1034,12 @@ impl Drop for ScopeExitGuard } - /// Extend the `ArrayVec` with an iterator. -/// +/// /// ***Panics*** if extending the vector exceeds its capacity. -impl Extend for ArrayVec { +impl Extend for ArrayVec { /// Extend the `ArrayVec` with an iterator. - /// + /// /// ***Panics*** if extending the vector exceeds its capacity. #[track_caller] fn extend>(&mut self, iter: I) { @@ -1058,7 +1056,7 @@ fn extend_panic() { panic!("ArrayVec: capacity exceeded in extend/from_iter"); } -impl ArrayVec { +impl ArrayVec { /// Extend the arrayvec from the iterable. /// /// ## Safety @@ -1067,7 +1065,7 @@ impl ArrayVec { /// The caller must ensure the length of the input fits in the capacity. #[track_caller] pub(crate) unsafe fn extend_from_iter(&mut self, iterable: I) - where I: IntoIterator + where I: IntoIterator { let take = self.capacity() - self.len(); let len = self.len(); @@ -1081,8 +1079,8 @@ impl ArrayVec { value: &mut self.len, data: len, f: move |&len, self_len| { - **self_len = len as LenUint; - } + **self_len = LenUint::from_usize(len); + }, }; let mut iter = iterable.into_iter(); loop { @@ -1123,11 +1121,11 @@ unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { } /// Create an `ArrayVec` from an iterator. -/// +/// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. -impl iter::FromIterator for ArrayVec { +impl iter::FromIterator for ArrayVec { /// Create an `ArrayVec` from an iterator. - /// + /// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. fn from_iter>(iter: I) -> Self { let mut array = ArrayVec::new(); @@ -1136,7 +1134,7 @@ impl iter::FromIterator for ArrayVec { } } -impl Clone for ArrayVec +impl Clone for ArrayVec where T: Clone { fn clone(&self) -> Self { @@ -1158,7 +1156,7 @@ impl Clone for ArrayVec } } -impl Hash for ArrayVec +impl Hash for ArrayVec where T: Hash { fn hash(&self, state: &mut H) { @@ -1166,7 +1164,7 @@ impl Hash for ArrayVec } } -impl PartialEq for ArrayVec +impl PartialEq for ArrayVec where T: PartialEq { fn eq(&self, other: &Self) -> bool { @@ -1174,7 +1172,7 @@ impl PartialEq for ArrayVec } } -impl PartialEq<[T]> for ArrayVec +impl PartialEq<[T]> for ArrayVec where T: PartialEq { fn eq(&self, other: &[T]) -> bool { @@ -1182,36 +1180,36 @@ impl PartialEq<[T]> for ArrayVec } } -impl Eq for ArrayVec where T: Eq { } +impl Eq for ArrayVec where T: Eq {} -impl Borrow<[T]> for ArrayVec { +impl Borrow<[T]> for ArrayVec { fn borrow(&self) -> &[T] { self } } -impl BorrowMut<[T]> for ArrayVec { +impl BorrowMut<[T]> for ArrayVec { fn borrow_mut(&mut self) -> &mut [T] { self } } -impl AsRef<[T]> for ArrayVec { +impl AsRef<[T]> for ArrayVec { fn as_ref(&self) -> &[T] { self } } -impl AsMut<[T]> for ArrayVec { +impl AsMut<[T]> for ArrayVec { fn as_mut(&mut self) -> &mut [T] { self } } -impl fmt::Debug for ArrayVec where T: 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() -> Self { ArrayVec::new() } } -impl PartialOrd for ArrayVec where T: PartialOrd { +impl PartialOrd for ArrayVec where T: PartialOrd { fn partial_cmp(&self, other: &Self) -> Option { (**self).partial_cmp(other) } @@ -1233,13 +1231,13 @@ impl PartialOrd for ArrayVec where T: PartialOrd { } } -impl Ord for ArrayVec where T: Ord { +impl Ord for ArrayVec where T: Ord { fn cmp(&self, other: &Self) -> cmp::Ordering { (**self).cmp(other) } } -#[cfg(feature="std")] +#[cfg(feature = "std")] /// `Write` appends written data to the end of the vector. /// /// Requires `features="std"`. @@ -1253,7 +1251,7 @@ impl io::Write for ArrayVec { fn flush(&mut self) -> io::Result<()> { Ok(()) } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` impl Serialize for ArrayVec { fn serialize(&self, serializer: S) -> Result @@ -1263,7 +1261,7 @@ impl Serialize for ArrayVec { } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec { fn deserialize(deserializer: D) -> Result diff --git a/src/lib.rs b/src/lib.rs index f9a2fe6..aeae082 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,28 +28,48 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -pub(crate) type LenUint = u32; - +pub trait LenUint: Add + Sub + Copy + PartialOrd + PartialEq + private::Sealed { + const MAX: usize; + const ZERO: Self; + fn from_usize(n: usize) -> Self; + fn to_usize(self) -> usize; +} +macro_rules! impl_lenuint { + ($ty: path) => { + impl $crate::private::Sealed for $ty {} + impl $crate::LenUint for $ty { + const MAX: usize = <$ty>::MAX as usize; + const ZERO: Self = 0; + fn from_usize(n: usize) -> Self { n as $ty } + fn to_usize(self) -> usize { self as usize } + } + }; +} +mod private { + pub trait Sealed {} + impl_lenuint!(u8); + impl_lenuint!(u16); + impl_lenuint!(u32); + #[cfg(target_pointer_width = "64")] + impl_lenuint!(u64); + impl_lenuint!(usize); +} macro_rules! assert_capacity_limit { - ($cap:expr) => { - if std::mem::size_of::() > std::mem::size_of::() { - if $cap > LenUint::MAX as usize { - panic!("ArrayVec: largest supported capacity is u32::MAX") - } + ($ty: path, $cap:expr) => { + if $cap > <$ty as LenUint>::MAX { + panic!("ArrayVec: capacity {} is too large for {}::MAX={}", CAP, std::any::type_name::<$ty>(), <$ty as LenUint>::MAX) } } } macro_rules! assert_capacity_limit_const { - ($cap:expr) => { - if std::mem::size_of::() > std::mem::size_of::() { - if $cap > LenUint::MAX as usize { - [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap] - } + ($ty: path, $cap:expr) => { + if $cap > <$ty as LenUint>::MAX { + panic!("ArrayVec: capacity is too large for LenUint::MAX") } } } - +pub type DefaultLenUint = u32; mod arrayvec_impl; mod arrayvec; mod array_string; @@ -57,6 +77,8 @@ mod char; mod errors; mod utils; +use core::ops::Sub; +use std::ops::Add; pub use crate::array_string::ArrayString; pub use crate::errors::CapacityError; diff --git a/src/utils.rs b/src/utils.rs index b8e5ddb..b425a51 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,4 +8,3 @@ impl MakeMaybeUninit { pub(crate) const ARRAY: [MaybeUninit; N] = [Self::VALUE; N]; } - diff --git a/tests/tests.rs b/tests/tests.rs index 2f8a5ef..715cf93 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,5 +1,6 @@ extern crate arrayvec; -#[macro_use] extern crate matches; +#[macro_use] +extern crate matches; use arrayvec::ArrayVec; use arrayvec::ArrayString; @@ -13,7 +14,7 @@ use std::collections::HashMap; fn test_simple() { use std::ops::Add; - let mut vec: ArrayVec, 3> = ArrayVec::new(); + let mut vec: ArrayVec, 3> = ArrayVec::new(); vec.push(vec![1, 2, 3, 4]); vec.push(vec![10]); @@ -29,7 +30,7 @@ fn test_simple() { #[test] fn test_capacity_left() { - let mut vec: ArrayVec = 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 +44,7 @@ fn test_capacity_left() { #[test] fn test_extend_from_slice() { - let mut vec: ArrayVec = ArrayVec::new(); + let mut vec: ArrayVec = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); assert_eq!(vec.len(), 3); @@ -54,13 +55,13 @@ fn test_extend_from_slice() { #[test] fn test_extend_from_slice_error() { - let mut vec: ArrayVec = 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 = ArrayVec::new(); + let mut vec: ArrayVec = ArrayVec::new(); let res = vec.try_extend_from_slice(&[0; 1]); assert_matches!(res, Err(_)); } @@ -70,14 +71,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()); } @@ -87,7 +88,8 @@ fn test_u16_index() { #[test] fn test_iter() { - let mut iter = ArrayVec::from([1, 2, 3]).into_iter(); + let vec: ArrayVec<_, 3> = ArrayVec::from([1, 2, 3]); + let mut iter = vec.into_iter(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(iter.next_back(), Some(3)); assert_eq!(iter.next(), Some(1)); @@ -113,7 +115,7 @@ fn test_drop() { } { - let mut array = ArrayVec::::new(); + let mut array = ArrayVec::::new(); array.push(Bump(flag)); array.push(Bump(flag)); } @@ -123,7 +125,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 +144,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 +158,7 @@ fn test_drop() { // test take flag.set(0); { - let mut array1 = ArrayVec::<_, 3>::new(); + let mut array1 = ArrayVec::<_, 3>::new(); array1.push(Bump(flag)); array1.push(Bump(flag)); array1.push(Bump(flag)); @@ -171,7 +173,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)); @@ -225,7 +227,7 @@ fn test_drop_panics() { flag.set(0); { - let mut array = ArrayVec::::new(); + let mut array = ArrayVec::::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -241,7 +243,7 @@ fn test_drop_panics() { flag.set(0); { - let mut array = ArrayVec::::new(); + let mut array = ArrayVec::::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); @@ -258,22 +260,20 @@ fn test_drop_panics() { // Check that all the tail elements drop, even if the first drop panics. assert_eq!(flag.get(), tail_len as i32); } - - } #[test] fn test_extend() { let mut range = 0..10; - let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().take(0)); 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]); @@ -284,7 +284,7 @@ fn test_extend() { fn test_extend_capacity_panic_1() { let mut range = 0..10; - let _: ArrayVec<_, 5> = range.by_ref().collect(); + let _: ArrayVec<_, 5> = range.by_ref().collect(); } #[should_panic] @@ -292,7 +292,7 @@ fn test_extend_capacity_panic_1() { fn test_extend_capacity_panic_2() { let mut range = 0..10; - let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().take(1)); @@ -300,7 +300,7 @@ fn test_extend_capacity_panic_2() { #[test] fn test_is_send_sync() { - let data = ArrayVec::, 5>::new(); + let data = ArrayVec::, 5>::new(); &data as &dyn Send; &data as &dyn Sync; } @@ -308,24 +308,24 @@ fn test_is_send_sync() { #[test] fn test_compact_size() { // 4 bytes + padding + length - type ByteArray = ArrayVec; + type ByteArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 2 * mem::size_of::()); // just length - type EmptyArray = ArrayVec; + type EmptyArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= mem::size_of::()); // 3 elements + padding + length - type QuadArray = ArrayVec; + type QuadArray = ArrayVec; println!("{}", mem::size_of::()); 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); @@ -333,7 +333,7 @@ fn test_still_works_with_option_arrayvec() { #[test] fn test_drain() { - let mut v = ArrayVec::from([0; 8]); + let mut v: ArrayVec = ArrayVec::from([0; 8]); v.pop(); v.drain(0..7); assert_eq!(&v[..], &[]); @@ -341,7 +341,7 @@ fn test_drain() { v.extend(0..8); 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(..); @@ -350,14 +350,14 @@ fn test_drain() { #[test] fn test_drain_range_inclusive() { - let mut v = ArrayVec::from([0; 8]); + let mut v: ArrayVec<_, 8> = ArrayVec::from([0; 8]); v.drain(0..=7); assert_eq!(&v[..], &[]); v.extend(0..8); 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(..); @@ -367,13 +367,13 @@ fn test_drain_range_inclusive() { #[test] #[should_panic] fn test_drain_range_inclusive_oob() { - let mut v = ArrayVec::from([0; 0]); + let mut v: ArrayVec<_, 0> = ArrayVec::from([0; 0]); v.drain(0..=0); } #[test] fn test_retain() { - let mut v = ArrayVec::from([0; 8]); + let mut v: ArrayVec<_, 8> = ArrayVec::from([0; 8]); for (i, elt) in v.iter_mut().enumerate() { *elt = i; } @@ -391,7 +391,7 @@ fn test_retain() { #[test] #[should_panic] fn test_drain_oob() { - let mut v = ArrayVec::from([0; 8]); + let mut v: ArrayVec<_, 8> = ArrayVec::from([0; 8]); v.pop(); v.drain(0..8); } @@ -407,7 +407,7 @@ fn test_drop_panic() { } } - let mut array = ArrayVec::::new(); + let mut array = ArrayVec::::new(); array.push(DropPanic); } @@ -422,17 +422,17 @@ fn test_drop_panic_into_iter() { } } - let mut array = ArrayVec::::new(); + let mut array = ArrayVec::::new(); array.push(DropPanic); array.into_iter(); } #[test] fn test_insert() { - let mut v = ArrayVec::from([]); + let mut v: ArrayVec<_, 0> = 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); @@ -445,7 +445,7 @@ fn test_insert() { assert_eq!(&v[..], &[0, 1, 2]); assert_matches!(ret2, Err(_)); - let mut v = ArrayVec::from([2]); + let mut v: ArrayVec<_, 1> = ArrayVec::from([2]); assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. })); assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. })); //assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. })); @@ -453,7 +453,7 @@ fn test_insert() { #[test] fn test_into_inner_1() { - let mut v = ArrayVec::from([1, 2]); + let mut v: ArrayVec<_, 2> = ArrayVec::from([1, 2]); v.pop(); let u = v.clone(); assert_eq!(v.into_inner(), Err(u)); @@ -461,7 +461,7 @@ fn test_into_inner_1() { #[test] fn test_into_inner_2() { - let mut v = ArrayVec::::new(); + let mut v = ArrayVec::::new(); v.push("a".into()); v.push("b".into()); v.push("c".into()); @@ -471,25 +471,25 @@ fn test_into_inner_2() { #[test] fn test_into_inner_3() { - let mut v = ArrayVec::::new(); + let mut v = ArrayVec::::new(); v.extend(1..=4); assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); } #[test] fn test_take() { - let mut v1 = ArrayVec::::new(); + let mut v1 = ArrayVec::::new(); v1.extend(1..=4); let v2 = v1.take(); assert!(v1.into_inner().is_err()); assert_eq!(v2.into_inner().unwrap(), [1, 2, 3, 4]); } -#[cfg(feature="std")] +#[cfg(feature = "std")] #[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(); @@ -499,16 +499,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]); @@ -520,7 +520,7 @@ fn array_clone_from() { assert_eq!(&t, &reference[..]); } -#[cfg(feature="std")] +#[cfg(feature = "std")] #[test] fn test_string() { use std::error::Error; @@ -557,7 +557,7 @@ fn test_string() { #[test] fn test_string_from() { let text = "hello world"; - // Test `from` constructor + // Test `from` constructor let u = ArrayString::<11>::from(text).unwrap(); assert_eq!(&u, text); assert_eq!(u.len(), text.len()); @@ -574,7 +574,7 @@ fn test_string_parse_from_str() { #[test] fn test_string_from_bytes() { let text = "hello world"; - let u = ArrayString::from_byte_string(b"hello world").unwrap(); + let u: ArrayString<11> = ArrayString::from_byte_string(b"hello world").unwrap(); assert_eq!(&u, text); assert_eq!(u.len(), text.len()); } @@ -607,7 +607,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()); @@ -617,7 +617,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"); } @@ -650,7 +650,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); @@ -665,7 +665,7 @@ fn test_drop_in_insert() { #[test] fn test_pop_at() { - let mut v = ArrayVec::::new(); + let mut v = ArrayVec::::new(); let s = String::from; v.push(s("a")); v.push(s("b")); @@ -681,7 +681,7 @@ fn test_pop_at() { #[test] fn test_sizes() { - let v = ArrayVec::from([0u8; 1 << 16]); + let v: ArrayVec<_, { 1 << 16 }> = ArrayVec::from([0u8; 1 << 16]); assert_eq!(vec![0u8; v.len()], &v[..]); } @@ -690,19 +690,19 @@ fn test_default() { use std::net; let s: ArrayString<4> = Default::default(); // Something without `Default` implementation. - let v: ArrayVec = Default::default(); + let v: ArrayVec = Default::default(); assert_eq!(s.len(), 0); assert_eq!(v.len(), 0); } -#[cfg(feature="array-sizes-33-128")] +#[cfg(feature = "array-sizes-33-128")] #[test] fn test_sizes_33_128() { ArrayVec::from([0u8; 52]); ArrayVec::from([0u8; 127]); } -#[cfg(feature="array-sizes-129-255")] +#[cfg(feature = "array-sizes-129-255")] #[test] fn test_sizes_129_255() { ArrayVec::from([0u8; 237]); @@ -715,14 +715,14 @@ fn test_extend_zst() { #[derive(Copy, Clone, PartialEq, Debug)] struct Z; // Zero sized type - let mut array: ArrayVec<_, 5> = range.by_ref().take(5).map(|_| Z).collect(); + let mut array: ArrayVec<_, 5> = range.by_ref().take(5).map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 5]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().take(0).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]); @@ -739,27 +739,27 @@ fn test_try_from_argument() { #[test] fn allow_max_capacity_arrayvec_type() { // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), {usize::MAX}>; + let _v: ArrayVec<(), { usize::MAX }>; } -#[should_panic(expected="largest supported capacity")] +#[should_panic(expected = "largest supported capacity")] #[test] fn deny_max_capacity_arrayvec_value() { if mem::size_of::() <= mem::size_of::() { panic!("This test does not work on this platform. 'largest supported capacity'"); } // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); + let _v: ArrayVec<(), { usize::MAX }> = ArrayVec::new(); } -#[should_panic(expected="index out of bounds")] +#[should_panic(expected = "index out of bounds")] #[test] fn deny_max_capacity_arrayvec_value_const() { if mem::size_of::() <= mem::size_of::() { panic!("This test does not work on this platform. 'index out of bounds'"); } // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const(); + let _v: ArrayVec<(), { usize::MAX }> = ArrayVec::new_const(); } #[test] From eefee318d10ae02cdeec123c96567ece0962a20c Mon Sep 17 00:00:00 2001 From: JakkuSakura Date: Fri, 29 Dec 2023 22:58:04 +0900 Subject: [PATCH 3/7] feat: fix Serialize and Deserialize --- src/arrayvec.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index b101025..dcee4b1 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1253,7 +1253,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 { @@ -1263,17 +1263,17 @@ impl Serialize for ArrayVec { #[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec { +impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> 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>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>); + struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint>(PhantomData<(&'de (), [T; CAP], LenType)>); - impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> { - type Value = ArrayVec; + impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Visitor<'de> for ArrayVecVisitor<'de, T, CAP, LenType> { + type Value = ArrayVec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "an array with no more than {} items", CAP) @@ -1282,7 +1282,7 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec(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) { @@ -1294,6 +1294,6 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec(PhantomData)) + deserializer.deserialize_seq(ArrayVecVisitor::(PhantomData)) } } From 207ffca0d0d98b0e52027af4917695da2d2f2f51 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Sun, 31 Mar 2024 00:18:38 +0000 Subject: [PATCH 4/7] Allow ArrayVec to be generic with efficent default LenT --- src/array_string.rs | 8 ++--- src/arrayvec.rs | 14 +++++---- src/len_type.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 46 ++--------------------------- tests/tests.rs | 26 ---------------- 5 files changed, 86 insertions(+), 80 deletions(-) create mode 100644 src/len_type.rs diff --git a/src/array_string.rs b/src/array_string.rs index 1a7c790..3153150 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -11,8 +11,8 @@ use std::str; use std::str::FromStr; use std::str::Utf8Error; -use crate::{CapacityError, DefaultLenUint}; -use crate::LenUint; +use crate::len_type::{LenUint, DefaultLenType, assert_capacity_limit, assert_capacity_limit_const}; +use crate::CapacityError; use crate::char::encode_utf8; use crate::utils::MakeMaybeUninit; @@ -32,7 +32,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer}; /// if needed. #[derive(Copy)] #[repr(C)] -pub struct ArrayString { +pub struct ArrayString> { // the `len` first elements of the array are initialized len: LenType, xs: [MaybeUninit; CAP], @@ -114,7 +114,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); + /// let string = ArrayString::<11>::from_byte_string(b"hello world").unwrap(); /// ``` pub fn from_byte_string(b: &[u8; CAP]) -> Result { let len = str::from_utf8(b)?.len(); diff --git a/src/arrayvec.rs b/src/arrayvec.rs index dcee4b1..5e479e3 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -19,7 +19,7 @@ use std::mem::MaybeUninit; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use crate::{DefaultLenUint, LenUint}; +use crate::len_type::{LenUint, CapToLenType, CapToDefaultLenType, DefaultLenType, assert_capacity_limit, assert_capacity_limit_const}; use crate::errors::CapacityError; use crate::arrayvec_impl::ArrayVecImpl; use crate::utils::MakeMaybeUninit; @@ -39,8 +39,8 @@ use crate::utils::MakeMaybeUninit; /// It offers a simple API but also dereferences to a slice, so that the full slice API is /// available. The ArrayVec can be converted into a by value iterator. #[repr(C)] -pub struct ArrayVec { - len: LenType, +pub struct ArrayVec> { + len: LenT, // the `len` first elements of the array are initialized xs: [MaybeUninit; CAP], } @@ -750,7 +750,9 @@ impl DerefMut for ArrayVec From<[T; CAP]> for ArrayVec { +impl From<[T; CAP]> for ArrayVec + where CapToLenType: CapToDefaultLenType +{ #[track_caller] fn from(array: [T; CAP]) -> Self { let array = ManuallyDrop::new(array); @@ -874,7 +876,7 @@ impl zeroize::Zeroize f } /// By-value iterator for `ArrayVec`. -pub struct IntoIter { +pub struct IntoIter> { index: usize, v: ArrayVec, } @@ -1241,7 +1243,7 @@ impl Ord for ArrayVec wh /// `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]); diff --git a/src/len_type.rs b/src/len_type.rs new file mode 100644 index 0000000..53153ae --- /dev/null +++ b/src/len_type.rs @@ -0,0 +1,72 @@ +use core::ops::{Add, Sub}; + +macro_rules! impl_lenuint { + ($Sealed:ty, $LenUint:ty, $ty: path) => { + impl $Sealed for $ty {} + impl $LenUint for $ty { + const MAX: usize = <$ty>::MAX as usize; + const ZERO: Self = 0; + fn from_usize(n: usize) -> Self { n as $ty } + fn to_usize(self) -> usize { self as usize } + } + }; +} + +macro_rules! impl_default_lentype_from_cap { + ($LenT:ty => $($CAP:literal),*) => { + $( + impl CapToDefaultLenType for CapToLenType<$CAP> { + type T = $LenT; + } + )* + }; +} + +macro_rules! assert_capacity_limit { + ($ty: path, $cap:expr) => { + if $cap > <$ty as LenUint>::MAX { + panic!("ArrayVec: capacity {} is too large for {}::MAX={}", CAP, std::any::type_name::<$ty>(), <$ty as LenUint>::MAX) + } + } +} + +macro_rules! assert_capacity_limit_const { + ($ty: path, $cap:expr) => { + if $cap > <$ty as LenUint>::MAX { + panic!("ArrayVec: capacity is too large for LenUint::MAX") + } + } +} + +pub trait LenUint: Add + Sub + Copy + PartialOrd + PartialEq + private::Sealed { + const MAX: usize; + const ZERO: Self; + fn from_usize(n: usize) -> Self; + fn to_usize(self) -> usize; +} + +mod private { + pub trait Sealed {} + + impl_lenuint!(Sealed, super::LenUint, u8); + impl_lenuint!(Sealed, super::LenUint, u16); + impl_lenuint!(Sealed, super::LenUint, u32); + #[cfg(target_pointer_width = "64")] + impl_lenuint!(Sealed, super::LenUint, u64); + impl_lenuint!(Sealed, super::LenUint, usize); +} + +pub struct CapToLenType {} + +pub trait CapToDefaultLenType { + type T: LenUint; +} + +impl_default_lentype_from_cap!(u8 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64, 100, 128, 200, 255); +impl_default_lentype_from_cap!(u16 => 256, 500, 512, 1000, 1024, 2048, 4096, 8192, 16384, 32768, 65535); +impl_default_lentype_from_cap!(u32 => 65536, 1000000, 4294967295); +impl_default_lentype_from_cap!(u64 => 18446744073709551615); + +pub(crate) type DefaultLenType = as CapToDefaultLenType>::T; + +pub(crate) use {assert_capacity_limit, assert_capacity_limit_const}; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index aeae082..9b6cbda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,48 +28,7 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -pub trait LenUint: Add + Sub + Copy + PartialOrd + PartialEq + private::Sealed { - const MAX: usize; - const ZERO: Self; - fn from_usize(n: usize) -> Self; - fn to_usize(self) -> usize; -} -macro_rules! impl_lenuint { - ($ty: path) => { - impl $crate::private::Sealed for $ty {} - impl $crate::LenUint for $ty { - const MAX: usize = <$ty>::MAX as usize; - const ZERO: Self = 0; - fn from_usize(n: usize) -> Self { n as $ty } - fn to_usize(self) -> usize { self as usize } - } - }; -} -mod private { - pub trait Sealed {} - impl_lenuint!(u8); - impl_lenuint!(u16); - impl_lenuint!(u32); - #[cfg(target_pointer_width = "64")] - impl_lenuint!(u64); - impl_lenuint!(usize); -} -macro_rules! assert_capacity_limit { - ($ty: path, $cap:expr) => { - if $cap > <$ty as LenUint>::MAX { - panic!("ArrayVec: capacity {} is too large for {}::MAX={}", CAP, std::any::type_name::<$ty>(), <$ty as LenUint>::MAX) - } - } -} - -macro_rules! assert_capacity_limit_const { - ($ty: path, $cap:expr) => { - if $cap > <$ty as LenUint>::MAX { - panic!("ArrayVec: capacity is too large for LenUint::MAX") - } - } -} -pub type DefaultLenUint = u32; +mod len_type; mod arrayvec_impl; mod arrayvec; mod array_string; @@ -77,9 +36,8 @@ mod char; mod errors; mod utils; -use core::ops::Sub; -use std::ops::Add; pub use crate::array_string::ArrayString; pub use crate::errors::CapacityError; +pub use len_type::LenUint; pub use crate::arrayvec::{ArrayVec, IntoIter, Drain}; diff --git a/tests/tests.rs b/tests/tests.rs index 715cf93..ffd6729 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -736,32 +736,6 @@ fn test_try_from_argument() { assert_eq!(&v, "Hello 123"); } -#[test] -fn allow_max_capacity_arrayvec_type() { - // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), { usize::MAX }>; -} - -#[should_panic(expected = "largest supported capacity")] -#[test] -fn deny_max_capacity_arrayvec_value() { - if mem::size_of::() <= mem::size_of::() { - panic!("This test does not work on this platform. 'largest supported capacity'"); - } - // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), { usize::MAX }> = ArrayVec::new(); -} - -#[should_panic(expected = "index out of bounds")] -#[test] -fn deny_max_capacity_arrayvec_value_const() { - if mem::size_of::() <= mem::size_of::() { - panic!("This test does not work on this platform. 'index out of bounds'"); - } - // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), { usize::MAX }> = ArrayVec::new_const(); -} - #[test] fn test_arrayvec_const_constructible() { const OF_U8: ArrayVec, 10> = ArrayVec::new_const(); From f4dbf750b53f37a3913791cd90244200ae114b55 Mon Sep 17 00:00:00 2001 From: David Thomas Date: Sun, 31 Mar 2024 13:57:38 +0100 Subject: [PATCH 5/7] Move CAP overflow check to compile time --- src/array_string.rs | 20 +++++++++++++++----- src/arrayvec.rs | 9 +++++---- src/len_type.rs | 37 +++++++++++++++++-------------------- 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index 3153150..6c743d4 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -11,7 +11,7 @@ use std::str; use std::str::FromStr; use std::str::Utf8Error; -use crate::len_type::{LenUint, DefaultLenType, assert_capacity_limit, assert_capacity_limit_const}; +use crate::len_type::{check_cap_fits_in_len_type, DefaultLenType, LenUint}; use crate::CapacityError; use crate::char::encode_utf8; use crate::utils::MakeMaybeUninit; @@ -60,8 +60,13 @@ impl ArrayString /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` + /// + /// If you provide a capacity greater than a length type, this will fail at compile time. + /// ```compile_fail + /// let string = arrayvec::ArrayString::<256, u8>::new(); + /// ``` pub fn new() -> Self { - assert_capacity_limit!(LenType, CAP); + check_cap_fits_in_len_type::(); ArrayString { len: LenType::from_usize(0), xs: MakeMaybeUninit::ARRAY } } @@ -75,7 +80,7 @@ impl ArrayString /// const ARRAY: ArrayString<1024> = ArrayString::new_const(); /// ``` pub const fn new_const() -> Self { - assert_capacity_limit_const!(LenType, CAP); + check_cap_fits_in_len_type::(); ArrayString { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } @@ -137,10 +142,15 @@ impl ArrayString /// let string = ArrayString::<16>::zero_filled(); /// assert_eq!(string.len(), 16); /// ``` + /// + /// If you provide a capacity greater than a length type, this will fail at compile time. + /// ```compile_fail + /// let string = arrayvec::ArrayString::<256, u8>::zero_filled(); + /// ``` #[inline] pub fn zero_filled() -> Self { - assert_capacity_limit!(LenType, CAP); - // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and + check_cap_fits_in_len_type::(); + // SAFETY: `check_cap_fits_in_len_type` asserts that `len` won't overflow and // `zeroed` fully fills the array with nulls. unsafe { ArrayString { diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 5e479e3..6d9ddf5 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -19,7 +19,8 @@ use std::mem::MaybeUninit; #[cfg(feature = "serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use crate::len_type::{LenUint, CapToLenType, CapToDefaultLenType, DefaultLenType, assert_capacity_limit, assert_capacity_limit_const}; +use crate::len_type::{check_cap_fits_in_len_type, ConstGenericSmuggler, CapToDefaultLenType}; +use crate::len_type::{LenUint, DefaultLenType}; use crate::errors::CapacityError; use crate::arrayvec_impl::ArrayVecImpl; use crate::utils::MakeMaybeUninit; @@ -80,7 +81,7 @@ impl ArrayVec { #[inline] #[track_caller] pub fn new() -> Self { - assert_capacity_limit!(LenType, CAP); + check_cap_fits_in_len_type::(); ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } @@ -94,7 +95,7 @@ impl ArrayVec { /// static ARRAY: ArrayVec = ArrayVec::new_const(); /// ``` pub const fn new_const() -> Self { - assert_capacity_limit_const!(LenType, CAP); + check_cap_fits_in_len_type::(); ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } @@ -751,7 +752,7 @@ impl DerefMut for ArrayVec From<[T; CAP]> for ArrayVec - where CapToLenType: CapToDefaultLenType + where ConstGenericSmuggler: CapToDefaultLenType { #[track_caller] fn from(array: [T; CAP]) -> Self { diff --git a/src/len_type.rs b/src/len_type.rs index 53153ae..f9dfe8c 100644 --- a/src/len_type.rs +++ b/src/len_type.rs @@ -15,29 +15,13 @@ macro_rules! impl_lenuint { macro_rules! impl_default_lentype_from_cap { ($LenT:ty => $($CAP:literal),*) => { $( - impl CapToDefaultLenType for CapToLenType<$CAP> { + impl CapToDefaultLenType for ConstGenericSmuggler<$CAP> { type T = $LenT; } )* }; } -macro_rules! assert_capacity_limit { - ($ty: path, $cap:expr) => { - if $cap > <$ty as LenUint>::MAX { - panic!("ArrayVec: capacity {} is too large for {}::MAX={}", CAP, std::any::type_name::<$ty>(), <$ty as LenUint>::MAX) - } - } -} - -macro_rules! assert_capacity_limit_const { - ($ty: path, $cap:expr) => { - if $cap > <$ty as LenUint>::MAX { - panic!("ArrayVec: capacity is too large for LenUint::MAX") - } - } -} - pub trait LenUint: Add + Sub + Copy + PartialOrd + PartialEq + private::Sealed { const MAX: usize; const ZERO: Self; @@ -56,7 +40,7 @@ mod private { impl_lenuint!(Sealed, super::LenUint, usize); } -pub struct CapToLenType {} +pub struct ConstGenericSmuggler {} pub trait CapToDefaultLenType { type T: LenUint; @@ -67,6 +51,19 @@ impl_default_lentype_from_cap!(u16 => 256, 500, 512, 1000, 1024, 2048, 4096, 819 impl_default_lentype_from_cap!(u32 => 65536, 1000000, 4294967295); impl_default_lentype_from_cap!(u64 => 18446744073709551615); -pub(crate) type DefaultLenType = as CapToDefaultLenType>::T; +pub trait CapFitsInLenType { + const CHECK: (); +} + +impl CapFitsInLenType for (ConstGenericSmuggler, LenType) { + const CHECK: () = { + if CAP > LenType::MAX { + panic!("Cannot fit CAP into provided LenType"); + } + }; +} -pub(crate) use {assert_capacity_limit, assert_capacity_limit_const}; \ No newline at end of file +pub type DefaultLenType = as CapToDefaultLenType>::T; +pub const fn check_cap_fits_in_len_type() { + <(ConstGenericSmuggler, LenType) as CapFitsInLenType>::CHECK +} From 448b7bddecb9d92dab9d80aef881801b17940617 Mon Sep 17 00:00:00 2001 From: JakkuSakura Date: Fri, 5 Apr 2024 17:51:34 +0800 Subject: [PATCH 6/7] feat: fix merge conflicts --- src/arrayvec.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 3b8e0ff..1262f3b 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -881,7 +881,8 @@ pub struct IntoIter> index: usize, v: ArrayVec, } -impl IntoIter { + +impl IntoIter { /// Returns the remaining items of this iterator as a slice. pub fn as_slice(&self) -> &[T] { &self.v[self.index..] @@ -1317,8 +1318,8 @@ impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Deserialize<' #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` impl borsh::BorshSerialize for ArrayVec -where - T: borsh::BorshSerialize, + where + T: borsh::BorshSerialize, { fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { <[T] as borsh::BorshSerialize>::serialize(self.as_slice(), writer) @@ -1328,8 +1329,8 @@ where #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` impl borsh::BorshDeserialize for ArrayVec -where - T: borsh::BorshDeserialize, + where + T: borsh::BorshDeserialize, { fn deserialize_reader(reader: &mut R) -> borsh::io::Result { let mut values = Self::new(); From cd18081c6ef888c14abf847e650658897e07639b Mon Sep 17 00:00:00 2001 From: JakkuSakura Date: Fri, 5 Apr 2024 17:56:18 +0800 Subject: [PATCH 7/7] feat: fix merge conflicts --- src/array_string.rs | 6 +++--- src/arrayvec.rs | 4 ++-- tests/borsh.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index a9fe859..fcf0836 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -638,7 +638,7 @@ impl<'de, const CAP: usize, LenType: LenUint> Deserialize<'de> for ArrayString borsh::BorshSerialize for ArrayString { +impl borsh::BorshSerialize for ArrayString { fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { ::serialize(&*self, writer) } @@ -646,14 +646,14 @@ impl borsh::BorshSerialize for ArrayString { #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl borsh::BorshDeserialize for ArrayString { +impl borsh::BorshDeserialize for ArrayString { fn deserialize_reader(reader: &mut R) -> borsh::io::Result { let len = ::deserialize_reader(reader)? as usize; if len > CAP { return Err(borsh::io::Error::new( borsh::io::ErrorKind::InvalidData, format!("Expected a string no more than {} bytes long", CAP), - )) + )); } let mut buf = [0u8; CAP]; diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 1262f3b..f7993cf 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -1317,7 +1317,7 @@ impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Deserialize<' #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl borsh::BorshSerialize for ArrayVec +impl borsh::BorshSerialize for ArrayVec where T: borsh::BorshSerialize, { @@ -1328,7 +1328,7 @@ impl borsh::BorshSerialize for ArrayVec #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl borsh::BorshDeserialize for ArrayVec +impl borsh::BorshDeserialize for ArrayVec where T: borsh::BorshDeserialize, { diff --git a/tests/borsh.rs b/tests/borsh.rs index f05abcf..0f31481 100644 --- a/tests/borsh.rs +++ b/tests/borsh.rs @@ -59,7 +59,7 @@ mod array_string { #[test] fn test_full() { - let string = ArrayString::from_byte_string(b"hello world").unwrap(); + let string = ArrayString::<11>::from_byte_string(b"hello world").unwrap(); assert_ser(&string, b"\x0b\0\0\0hello world"); assert_roundtrip(&string); }