diff --git a/src/array_string.rs b/src/array_string.rs index 1144360..fcf0836 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::len_type::{check_cap_fits_in_len_type, DefaultLenType, LenUint}; use crate::CapacityError; -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<const CAP: usize> { +pub struct ArrayString<const CAP: usize, LenType: LenUint = DefaultLenType<CAP>> { // the `len` first elements of the array are initialized - len: LenUint, + len: LenType, xs: [MaybeUninit<u8>; CAP], } -impl<const CAP: usize> Default for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Default for ArrayString<CAP, LenType> { /// Return an empty `ArrayString` - fn default() -> ArrayString<CAP> { + fn default() -> Self { ArrayString::new() } } -impl<const CAP: usize> ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> ArrayString<CAP, LenType> { /// Create a new empty `ArrayString`. /// @@ -60,11 +60,14 @@ impl<const CAP: usize> ArrayString<CAP> /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` - pub fn new() -> ArrayString<CAP> { - assert_capacity_limit!(CAP); - unsafe { - ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } - } + /// + /// 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 { + check_cap_fits_in_len_type::<LenType, CAP>(); + ArrayString { len: LenType::from_usize(0), xs: MakeMaybeUninit::ARRAY } } /// Create a new empty `ArrayString` (const fn). @@ -74,20 +77,20 @@ impl<const CAP: usize> ArrayString<CAP> /// ``` /// use arrayvec::ArrayString; /// - /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); + /// const ARRAY: ArrayString<1024> = ArrayString::new_const(); /// ``` - pub const fn new_const() -> ArrayString<CAP> { - assert_capacity_limit_const!(CAP); - ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 } + pub const fn new_const() -> Self { + check_cap_fits_in_len_type::<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`. /// @@ -116,7 +119,7 @@ impl<const CAP: usize> ArrayString<CAP> /// ``` /// 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<Self, Utf8Error> { let len = str::from_utf8(b)?.len(); @@ -139,15 +142,20 @@ impl<const CAP: usize> ArrayString<CAP> /// 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!(CAP); - // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and + check_cap_fits_in_len_type::<LenType, CAP>(); + // SAFETY: `check_cap_fits_in_len_type` 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 +181,7 @@ impl<const CAP: usize> ArrayString<CAP> /// 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 +192,7 @@ impl<const CAP: usize> ArrayString<CAP> /// 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 +307,7 @@ impl<const CAP: usize> ArrayString<CAP> /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); @@ -339,7 +347,7 @@ impl<const CAP: usize> ArrayString<CAP> 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 +367,7 @@ impl<const CAP: usize> ArrayString<CAP> /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); @@ -402,7 +410,7 @@ impl<const CAP: usize> ArrayString<CAP> 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`. @@ -426,7 +434,7 @@ impl<const CAP: usize> ArrayString<CAP> } } -impl<const CAP: usize> Deref for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Deref for ArrayString<CAP, LenType> { type Target = str; #[inline] @@ -438,7 +446,7 @@ impl<const CAP: usize> Deref for ArrayString<CAP> } } -impl<const CAP: usize> DerefMut for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> DerefMut for ArrayString<CAP, LenType> { #[inline] fn deref_mut(&mut self) -> &mut str { @@ -450,64 +458,64 @@ impl<const CAP: usize> DerefMut for ArrayString<CAP> } } -impl<const CAP: usize> PartialEq for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> PartialEq for ArrayString<CAP, LenType> { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } -impl<const CAP: usize> PartialEq<str> for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> PartialEq<str> for ArrayString<CAP, LenType> { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } -impl<const CAP: usize> PartialEq<ArrayString<CAP>> for str +impl<const CAP: usize, LenType: LenUint> PartialEq<ArrayString<CAP, LenType>> for str { - fn eq(&self, rhs: &ArrayString<CAP>) -> bool { + fn eq(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self == &**rhs } } -impl<const CAP: usize> Eq for ArrayString<CAP> -{ } +impl<const CAP: usize, LenType: LenUint> Eq for ArrayString<CAP, LenType> +{} -impl<const CAP: usize> Hash for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Hash for ArrayString<CAP, LenType> { fn hash<H: Hasher>(&self, h: &mut H) { (**self).hash(h) } } -impl<const CAP: usize> Borrow<str> for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Borrow<str> for ArrayString<CAP, LenType> { fn borrow(&self) -> &str { self } } -impl<const CAP: usize> BorrowMut<str> for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> BorrowMut<str> for ArrayString<CAP, LenType> { fn borrow_mut(&mut self) -> &mut str { self } } -impl<const CAP: usize> AsRef<str> for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> AsRef<str> for ArrayString<CAP, LenType> { fn as_ref(&self) -> &str { self } } -impl<const CAP: usize> fmt::Debug for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> fmt::Debug for ArrayString<CAP, LenType> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl<const CAP: usize> fmt::Display for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> fmt::Display for ArrayString<CAP, LenType> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } /// `Write` appends written data to the end of the string. -impl<const CAP: usize> fmt::Write for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> fmt::Write for ArrayString<CAP, LenType> { fn write_char(&mut self, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error) @@ -518,9 +526,9 @@ impl<const CAP: usize> fmt::Write for ArrayString<CAP> } } -impl<const CAP: usize> Clone for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Clone for ArrayString<CAP, LenType> { - fn clone(&self) -> ArrayString<CAP> { + fn clone(&self) -> ArrayString<CAP, LenType> { *self } fn clone_from(&mut self, rhs: &Self) { @@ -530,7 +538,7 @@ impl<const CAP: usize> Clone for ArrayString<CAP> } } -impl<const CAP: usize> PartialOrd for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> PartialOrd for ArrayString<CAP, LenType> { fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> { (**self).partial_cmp(&**rhs) @@ -541,7 +549,7 @@ impl<const CAP: usize> PartialOrd for ArrayString<CAP> fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } } -impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> PartialOrd<str> for ArrayString<CAP, LenType> { fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> { (**self).partial_cmp(rhs) @@ -552,25 +560,25 @@ impl<const CAP: usize> PartialOrd<str> for ArrayString<CAP> fn ge(&self, rhs: &str) -> bool { &**self >= rhs } } -impl<const CAP: usize> PartialOrd<ArrayString<CAP>> for str +impl<const CAP: usize, LenType: LenUint> PartialOrd<ArrayString<CAP, LenType>> for str { - fn partial_cmp(&self, rhs: &ArrayString<CAP>) -> Option<cmp::Ordering> { + fn partial_cmp(&self, rhs: &ArrayString<CAP, LenType>) -> Option<cmp::Ordering> { self.partial_cmp(&**rhs) } - fn lt(&self, rhs: &ArrayString<CAP>) -> bool { self < &**rhs } - fn le(&self, rhs: &ArrayString<CAP>) -> bool { self <= &**rhs } - fn gt(&self, rhs: &ArrayString<CAP>) -> bool { self > &**rhs } - fn ge(&self, rhs: &ArrayString<CAP>) -> bool { self >= &**rhs } + fn lt(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self < &**rhs } + fn le(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self <= &**rhs } + fn gt(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self > &**rhs } + fn ge(&self, rhs: &ArrayString<CAP, LenType>) -> bool { self >= &**rhs } } -impl<const CAP: usize> Ord for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Ord for ArrayString<CAP, LenType> { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } -impl<const CAP: usize> FromStr for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> FromStr for ArrayString<CAP, LenType> { type Err = CapacityError; @@ -579,9 +587,9 @@ impl<const CAP: usize> FromStr for ArrayString<CAP> } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl<const CAP: usize> Serialize for ArrayString<CAP> +impl<const CAP: usize, LenType: LenUint> Serialize for ArrayString<CAP, LenType> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer @@ -590,9 +598,9 @@ impl<const CAP: usize> Serialize for ArrayString<CAP> } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP> +impl<'de, const CAP: usize, LenType: LenUint> Deserialize<'de> for ArrayString<CAP, LenType> { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> @@ -600,10 +608,10 @@ impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP> use serde::de::{self, Visitor}; use std::marker::PhantomData; - struct ArrayStringVisitor<const CAP: usize>(PhantomData<[u8; CAP]>); + struct ArrayStringVisitor<const CAP: usize, LenType: LenUint>(PhantomData<([u8; CAP], LenType)>); - impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor<CAP> { - type Value = ArrayString<CAP>; + impl<'de, const CAP: usize, LenType: LenUint> Visitor<'de> for ArrayStringVisitor<CAP, LenType> { + type Value = ArrayString<CAP, LenType>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a string no more than {} bytes long", CAP) @@ -630,7 +638,7 @@ impl<'de, const CAP: usize> Deserialize<'de> for ArrayString<CAP> #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl<const CAP: usize> borsh::BorshSerialize for ArrayString<CAP> { +impl<const CAP: usize, LenType: LenUint> borsh::BorshSerialize for ArrayString<CAP, LenType> { fn serialize<W: borsh::io::Write>(&self, writer: &mut W) -> borsh::io::Result<()> { <str as borsh::BorshSerialize>::serialize(&*self, writer) } @@ -638,14 +646,14 @@ impl<const CAP: usize> borsh::BorshSerialize for ArrayString<CAP> { #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl<const CAP: usize> borsh::BorshDeserialize for ArrayString<CAP> { +impl<const CAP: usize, LenType: LenUint> borsh::BorshDeserialize for ArrayString<CAP, LenType> { fn deserialize_reader<R: borsh::io::Read>(reader: &mut R) -> borsh::io::Result<Self> { let len = <u32 as borsh::BorshDeserialize>::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]; @@ -659,7 +667,7 @@ impl<const CAP: usize> borsh::BorshDeserialize for ArrayString<CAP> { } } -impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString<CAP> +impl<'a, const CAP: usize, LenType: LenUint> TryFrom<&'a str> for ArrayString<CAP, LenType> { type Error = CapacityError<&'a str>; @@ -670,7 +678,7 @@ impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString<CAP> } } -impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP> +impl<'a, const CAP: usize, LenType: LenUint> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP, LenType> { type Error = CapacityError<fmt::Error>; @@ -697,7 +705,7 @@ impl<'a, const CAP: usize> TryFrom<fmt::Arguments<'a>> for ArrayString<CAP> /// unsafe { string.set_len(string.capacity()) }; /// assert_eq!(&*string, "\0\0\0\0\0\0"); /// ``` -impl<const CAP: usize> zeroize::Zeroize for ArrayString<CAP> { +impl<const CAP: usize, LenType: LenUint> zeroize::Zeroize for ArrayString<CAP, LenType> { fn zeroize(&mut self) { // There are no elements to drop self.clear(); diff --git a/src/arrayvec.rs b/src/arrayvec.rs index e87b3ef..f7993cf 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,17 @@ 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::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; @@ -40,13 +40,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<T, const CAP: usize> { - len: LenUint, +pub struct ArrayVec<T, const CAP: usize, LenT: LenUint = DefaultLenType<CAP>> { + len: LenT, // the `len` first elements of the array are initialized xs: [MaybeUninit<T>; CAP], } -impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Drop for ArrayVec<T, CAP, LenType> { fn drop(&mut self) { self.clear(); @@ -61,7 +61,7 @@ macro_rules! panic_oob { } } -impl<T, const CAP: usize> ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> ArrayVec<T, CAP, LenType> { /// Capacity const CAPACITY: usize = CAP; @@ -80,11 +80,9 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// ``` #[inline] #[track_caller] - pub fn new() -> ArrayVec<T, CAP> { - assert_capacity_limit!(CAP); - unsafe { - ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } - } + pub fn new() -> Self { + check_cap_fits_in_len_type::<LenType, CAP>(); + ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } /// Create a new empty `ArrayVec` (const fn). @@ -96,9 +94,9 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// /// static ARRAY: ArrayVec<u8, 1024> = ArrayVec::new_const(); /// ``` - pub const fn new_const() -> ArrayVec<T, CAP> { - assert_capacity_limit_const!(CAP); - ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 } + pub const fn new_const() -> Self { + check_cap_fits_in_len_type::<LenType, CAP>(); + ArrayVec { len: LenType::ZERO, xs: MakeMaybeUninit::ARRAY } } /// Return the number of elements in the `ArrayVec`. @@ -111,7 +109,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// 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 +121,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// 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 +144,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// 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 +155,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// 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 +470,21 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { let original_len = self.len(); unsafe { self.set_len(0) }; - struct BackshiftOnDrop<'a, T, const CAP: usize> { - v: &'a mut ArrayVec<T, CAP>, + struct BackshiftOnDrop<'a, T, const CAP: usize, LenType: LenUint> { + v: &'a mut ArrayVec<T, CAP, LenType>, processed_len: usize, deleted_cnt: usize, original_len: usize, } - impl<T, const CAP: usize> Drop for BackshiftOnDrop<'_, T, CAP> { + impl<T, const CAP: usize, LenType: LenUint> 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 +497,9 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; #[inline(always)] - fn process_one<F: FnMut(&mut T) -> bool, T, const CAP: usize, const DELETED: bool>( + fn process_one<F: FnMut(&mut T) -> 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 +520,14 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { // Stage 1: Nothing was deleted. while g.processed_len != original_len { - if !process_one::<F, T, CAP, false>(&mut f, &mut g) { + if !process_one::<F, T, CAP, false, LenType>(&mut f, &mut g) { break; } } // Stage 2: Some elements were deleted. while g.processed_len != original_len { - process_one::<F, T, CAP, true>(&mut f, &mut g); + process_one::<F, T, CAP, true, LenType>(&mut f, &mut g); } drop(g); @@ -545,7 +543,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { 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 +600,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// assert_eq!(&v1[..], &[3]); /// assert_eq!(&v2[..], &[1, 2]); /// ``` - pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP> + pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP, LenType> where R: RangeBounds<usize> { // Memory safety @@ -629,7 +627,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { self.drain_range(start, end) } - fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP> + fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP, LenType> { let len = self.len(); @@ -638,7 +636,8 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { // 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 +681,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// 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 +706,15 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { } } -impl<T, const CAP: usize> ArrayVecImpl for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> ArrayVecImpl for ArrayVec<T, CAP, LenType> { 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 +726,7 @@ impl<T, const CAP: usize> ArrayVecImpl for ArrayVec<T, CAP> { } } -impl<T, const CAP: usize> Deref for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Deref for ArrayVec<T, CAP, LenType> { type Target = [T]; #[inline] fn deref(&self) -> &Self::Target { @@ -735,7 +734,7 @@ impl<T, const CAP: usize> Deref for ArrayVec<T, CAP> { } } -impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> DerefMut for ArrayVec<T, CAP, LenType> { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() @@ -752,11 +751,13 @@ impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> { /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 3); /// ``` -impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> { +impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> + where ConstGenericSmuggler<CAP>: CapToDefaultLenType +{ #[track_caller] fn from(array: [T; CAP]) -> Self { let array = ManuallyDrop::new(array); - let mut vec = <ArrayVec<T, CAP>>::new(); + let mut vec = Self::new(); unsafe { (&*array as *const [T; CAP] as *const [MaybeUninit<T>; CAP]) .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit<T>; CAP], 1); @@ -778,7 +779,7 @@ impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> { /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 4); /// ``` -impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP> +impl<T, const CAP: usize, LenType: LenUint> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP, LenType> where T: Clone, { type Error = CapacityError; @@ -806,7 +807,7 @@ impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP> /// // ... /// } /// ``` -impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec<T, CAP> { +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> IntoIterator for &'a ArrayVec<T, CAP, LenType> { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter() } @@ -823,7 +824,7 @@ impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec<T, CAP> { /// // ... /// } /// ``` -impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec<T, CAP> { +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> IntoIterator for &'a mut ArrayVec<T, CAP, LenType> { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } @@ -840,11 +841,11 @@ impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec<T, CAP> { /// // ... /// } /// ``` -impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> IntoIterator for ArrayVec<T, CAP, LenType> { type Item = T; - type IntoIter = IntoIter<T, CAP>; - fn into_iter(self) -> IntoIter<T, CAP> { - IntoIter { index: 0, v: self, } + type IntoIter = IntoIter<T, CAP, LenType>; + fn into_iter(self) -> Self::IntoIter { + IntoIter { index: 0, v: self } } } @@ -864,7 +865,7 @@ impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> { /// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) }; /// assert_eq!(data, [0, 0, 0]); /// ``` -impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP> { +impl<Z: zeroize::Zeroize, const CAP: usize, LenType: LenUint> zeroize::Zeroize for ArrayVec<Z, CAP, LenType> { fn zeroize(&mut self) { // Zeroize all the contained elements. self.iter_mut().zeroize(); @@ -876,11 +877,12 @@ impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP } /// By-value iterator for `ArrayVec`. -pub struct IntoIter<T, const CAP: usize> { +pub struct IntoIter<T, const CAP: usize, LenType: LenUint = DefaultLenType<CAP>> { index: usize, - v: ArrayVec<T, CAP>, + v: ArrayVec<T, CAP, LenType>, } -impl<T, const CAP: usize> IntoIter<T, CAP> { + +impl<T, const CAP: usize, LenType: LenUint> IntoIter<T, CAP, LenType> { /// Returns the remaining items of this iterator as a slice. pub fn as_slice(&self) -> &[T] { &self.v[self.index..] @@ -892,7 +894,7 @@ impl<T, const CAP: usize> IntoIter<T, CAP> { } } -impl<T, const CAP: usize> Iterator for IntoIter<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Iterator for IntoIter<T, CAP, LenType> { type Item = T; fn next(&mut self) -> Option<Self::Item> { @@ -913,7 +915,7 @@ impl<T, const CAP: usize> Iterator for IntoIter<T, CAP> { } } -impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> DoubleEndedIterator for IntoIter<T, CAP, LenType> { fn next_back(&mut self) -> Option<Self::Item> { if self.index == self.v.len() { None @@ -927,9 +929,9 @@ impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> { } } -impl<T, const CAP: usize> ExactSizeIterator for IntoIter<T, CAP> { } +impl<T, const CAP: usize, LenType: LenUint> ExactSizeIterator for IntoIter<T, CAP, LenType> {} -impl<T, const CAP: usize> Drop for IntoIter<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Drop for IntoIter<T, CAP, LenType> { fn drop(&mut self) { // panic safety: Set length to 0 before dropping elements. let index = self.index; @@ -944,19 +946,19 @@ impl<T, const CAP: usize> Drop for IntoIter<T, CAP> { } } -impl<T, const CAP: usize> Clone for IntoIter<T, CAP> -where T: Clone, +impl<T, const CAP: usize, LenType: LenUint> Clone for IntoIter<T, CAP, LenType> + where T: Clone, { - fn clone(&self) -> IntoIter<T, CAP> { + fn clone(&self) -> Self { let mut v = ArrayVec::new(); v.extend_from_slice(&self.v[self.index..]); v.into_iter() } } -impl<T, const CAP: usize> fmt::Debug for IntoIter<T, CAP> -where - T: fmt::Debug, +impl<T, const CAP: usize, LenType: LenUint> fmt::Debug for IntoIter<T, CAP, LenType> + where + T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() @@ -966,20 +968,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<T, CAP>, + vec: *mut ArrayVec<T, CAP, LenType>, } -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> {} -impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { +unsafe impl<'a, T: Send, const CAP: usize, LenType: LenUint> Send for Drain<'a, T, CAP, LenType> {} + +impl<'a, T: 'a, const CAP: usize, LenType: LenUint> Iterator for Drain<'a, T, CAP, LenType> { type Item = T; fn next(&mut self) -> Option<Self::Item> { @@ -995,7 +998,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::Item> { self.iter.next_back().map(|elt| @@ -1006,14 +1009,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 { @@ -1046,13 +1049,12 @@ impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F> } - /// Extend the `ArrayVec` with an iterator. -/// +/// /// ***Panics*** if extending the vector exceeds its capacity. -impl<T, const CAP: usize> Extend<T> for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Extend<T> for ArrayVec<T, CAP, LenType> { /// Extend the `ArrayVec` with an iterator. - /// + /// /// ***Panics*** if extending the vector exceeds its capacity. #[track_caller] fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) { @@ -1069,7 +1071,7 @@ fn extend_panic() { panic!("ArrayVec: capacity exceeded in extend/from_iter"); } -impl<T, const CAP: usize> ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> ArrayVec<T, CAP, LenType> { /// Extend the arrayvec from the iterable. /// /// ## Safety @@ -1078,7 +1080,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { /// The caller must ensure the length of the input fits in the capacity. #[track_caller] pub(crate) unsafe fn extend_from_iter<I, const CHECK: bool>(&mut self, iterable: I) - where I: IntoIterator<Item = T> + where I: IntoIterator<Item=T> { let take = self.capacity() - self.len(); let len = self.len(); @@ -1092,8 +1094,8 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> { 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 { @@ -1136,11 +1138,11 @@ unsafe fn raw_ptr_add<T>(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<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> iter::FromIterator<T> for ArrayVec<T, CAP, LenType> { /// Create an `ArrayVec` from an iterator. - /// + /// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self { let mut array = ArrayVec::new(); @@ -1149,7 +1151,7 @@ impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> { } } -impl<T, const CAP: usize> Clone for ArrayVec<T, CAP> +impl<T, const CAP: usize, LenType: LenUint> Clone for ArrayVec<T, CAP, LenType> where T: Clone { fn clone(&self) -> Self { @@ -1171,7 +1173,7 @@ impl<T, const CAP: usize> Clone for ArrayVec<T, CAP> } } -impl<T, const CAP: usize> Hash for ArrayVec<T, CAP> +impl<T, const CAP: usize, LenType: LenUint> Hash for ArrayVec<T, CAP, LenType> where T: Hash { fn hash<H: Hasher>(&self, state: &mut H) { @@ -1179,7 +1181,7 @@ impl<T, const CAP: usize> Hash for ArrayVec<T, CAP> } } -impl<T, const CAP: usize> PartialEq for ArrayVec<T, CAP> +impl<T, const CAP: usize, LenType: LenUint> PartialEq for ArrayVec<T, CAP, LenType> where T: PartialEq { fn eq(&self, other: &Self) -> bool { @@ -1187,7 +1189,7 @@ impl<T, const CAP: usize> PartialEq for ArrayVec<T, CAP> } } -impl<T, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP> +impl<T, const CAP: usize, LenType: LenUint> PartialEq<[T]> for ArrayVec<T, CAP, LenType> where T: PartialEq { fn eq(&self, other: &[T]) -> bool { @@ -1195,36 +1197,36 @@ impl<T, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP> } } -impl<T, const CAP: usize> Eq for ArrayVec<T, CAP> where T: Eq { } +impl<T, const CAP: usize, LenType: LenUint> Eq for ArrayVec<T, CAP, LenType> where T: Eq {} -impl<T, const CAP: usize> Borrow<[T]> for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Borrow<[T]> for ArrayVec<T, CAP, LenType> { fn borrow(&self) -> &[T] { self } } -impl<T, const CAP: usize> BorrowMut<[T]> for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> BorrowMut<[T]> for ArrayVec<T, CAP, LenType> { fn borrow_mut(&mut self) -> &mut [T] { self } } -impl<T, const CAP: usize> AsRef<[T]> for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> AsRef<[T]> for ArrayVec<T, CAP, LenType> { fn as_ref(&self) -> &[T] { self } } -impl<T, const CAP: usize> AsMut<[T]> for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> AsMut<[T]> for ArrayVec<T, CAP, LenType> { fn as_mut(&mut self) -> &mut [T] { self } } -impl<T, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> where T: fmt::Debug { +impl<T, const CAP: usize, LenType: LenUint> fmt::Debug for ArrayVec<T, CAP, LenType> where T: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl<T, const CAP: usize> Default for ArrayVec<T, CAP> { +impl<T, const CAP: usize, LenType: LenUint> Default for ArrayVec<T, CAP, LenType> { /// Return an empty array - fn default() -> ArrayVec<T, CAP> { + fn default() -> Self { ArrayVec::new() } } -impl<T, const CAP: usize> PartialOrd for ArrayVec<T, CAP> where T: PartialOrd { +impl<T, const CAP: usize, LenType: LenUint> PartialOrd for ArrayVec<T, CAP, LenType> where T: PartialOrd { fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { (**self).partial_cmp(other) } @@ -1246,17 +1248,17 @@ impl<T, const CAP: usize> PartialOrd for ArrayVec<T, CAP> where T: PartialOrd { } } -impl<T, const CAP: usize> Ord for ArrayVec<T, CAP> where T: Ord { +impl<T, const CAP: usize, LenType: LenUint> Ord for ArrayVec<T, CAP, LenType> 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"`. -impl<const CAP: usize> io::Write for ArrayVec<u8, CAP> { +impl<const CAP: usize, LenType: LenUint> io::Write for ArrayVec<u8, CAP, LenType> { fn write(&mut self, data: &[u8]) -> io::Result<usize> { let len = cmp::min(self.remaining_capacity(), data.len()); let _result = self.try_extend_from_slice(&data[..len]); @@ -1266,9 +1268,9 @@ impl<const CAP: usize> io::Write for ArrayVec<u8, CAP> { fn flush(&mut self) -> io::Result<()> { Ok(()) } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> { +impl<T: Serialize, const CAP: usize, LenType: LenUint> Serialize for ArrayVec<T, CAP, LenType> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { @@ -1276,19 +1278,19 @@ impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> { } } -#[cfg(feature="serde")] +#[cfg(feature = "serde")] /// Requires crate feature `"serde"` -impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T, CAP> { +impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Deserialize<'de> for ArrayVec<T, CAP, LenType> { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 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<T, CAP>; + impl<'de, T: Deserialize<'de>, const CAP: usize, LenType: LenUint> Visitor<'de> for ArrayVecVisitor<'de, T, CAP, LenType> { + type Value = ArrayVec<T, CAP, LenType>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "an array with no more than {} items", CAP) @@ -1297,7 +1299,7 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error> where SA: SeqAccess<'de>, { - let mut values = ArrayVec::<T, CAP>::new(); + let mut values = ArrayVec::<T, CAP, LenType>::new(); while let Some(value) = seq.next_element()? { if let Err(_) = values.try_push(value) { @@ -1309,15 +1311,15 @@ impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T } } - deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP>(PhantomData)) + deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP, LenType>(PhantomData)) } } #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl<T, const CAP: usize> borsh::BorshSerialize for ArrayVec<T, CAP> -where - T: borsh::BorshSerialize, +impl<T, const CAP: usize, LenType: LenUint> borsh::BorshSerialize for ArrayVec<T, CAP, LenType> + where + T: borsh::BorshSerialize, { fn serialize<W: borsh::io::Write>(&self, writer: &mut W) -> borsh::io::Result<()> { <[T] as borsh::BorshSerialize>::serialize(self.as_slice(), writer) @@ -1326,9 +1328,9 @@ where #[cfg(feature = "borsh")] /// Requires crate feature `"borsh"` -impl<T, const CAP: usize> borsh::BorshDeserialize for ArrayVec<T, CAP> -where - T: borsh::BorshDeserialize, +impl<T, const CAP: usize, LenType: LenUint> borsh::BorshDeserialize for ArrayVec<T, CAP, LenType> + where + T: borsh::BorshDeserialize, { fn deserialize_reader<R: borsh::io::Read>(reader: &mut R) -> borsh::io::Result<Self> { let mut values = Self::new(); diff --git a/src/len_type.rs b/src/len_type.rs new file mode 100644 index 0000000..f9dfe8c --- /dev/null +++ b/src/len_type.rs @@ -0,0 +1,69 @@ +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 ConstGenericSmuggler<$CAP> { + type T = $LenT; + } + )* + }; +} + +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 ConstGenericSmuggler<const CONST: usize> {} + +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 trait CapFitsInLenType { + const CHECK: (); +} + +impl<LenType: LenUint, const CAP: usize> CapFitsInLenType for (ConstGenericSmuggler<CAP>, LenType) { + const CHECK: () = { + if CAP > LenType::MAX { + panic!("Cannot fit CAP into provided LenType"); + } + }; +} + +pub type DefaultLenType<const CAP: usize> = <ConstGenericSmuggler<CAP> as CapToDefaultLenType>::T; +pub const fn check_cap_fits_in_len_type<LenType: LenUint, const CAP: usize>() { + <(ConstGenericSmuggler<CAP>, LenType) as CapFitsInLenType>::CHECK +} diff --git a/src/lib.rs b/src/lib.rs index f9a2fe6..9b6cbda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,28 +28,7 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -pub(crate) type LenUint = u32; - -macro_rules! assert_capacity_limit { - ($cap:expr) => { - if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() { - if $cap > LenUint::MAX as usize { - panic!("ArrayVec: largest supported capacity is u32::MAX") - } - } - } -} - -macro_rules! assert_capacity_limit_const { - ($cap:expr) => { - if std::mem::size_of::<usize>() > std::mem::size_of::<LenUint>() { - if $cap > LenUint::MAX as usize { - [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap] - } - } - } -} - +mod len_type; mod arrayvec_impl; mod arrayvec; mod array_string; @@ -59,5 +38,6 @@ mod utils; 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/src/utils.rs b/src/utils.rs index b8e5ddb..b425a51 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,4 +8,3 @@ impl<T, const N: usize> MakeMaybeUninit<T, N> { pub(crate) const ARRAY: [MaybeUninit<T>; N] = [Self::VALUE; N]; } - 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); } diff --git a/tests/tests.rs b/tests/tests.rs index 2f8a5ef..ffd6729 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<Vec<i32>, 3> = ArrayVec::new(); + let mut vec: ArrayVec<Vec<i32>, 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<usize, 4> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 4> = 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<usize, 10> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 10> = 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<usize, 10> = ArrayVec::new(); + let mut vec: ArrayVec<usize, 10> = 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<usize, 0> = 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<ArrayVec<_, 2>, _> = (&[1, 2, 3] as &[_]).try_into(); + let res: Result<ArrayVec<_, 2>, _> = (&[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::<Bump, 128>::new(); + let mut array = ArrayVec::<Bump, 128>::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::<Bump, 128>::new(); + let mut array = ArrayVec::<Bump, 128>::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::<Bump, 16>::new(); + let mut array = ArrayVec::<Bump, 16>::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::<Vec<i32>, 5>::new(); + let data = ArrayVec::<Vec<i32>, 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<u8, 4>; + type ByteArray = ArrayVec<u8, 4>; println!("{}", mem::size_of::<ByteArray>()); assert!(mem::size_of::<ByteArray>() <= 2 * mem::size_of::<u32>()); // just length - type EmptyArray = ArrayVec<u8, 0>; + type EmptyArray = ArrayVec<u8, 0>; println!("{}", mem::size_of::<EmptyArray>()); assert!(mem::size_of::<EmptyArray>() <= mem::size_of::<u32>()); // 3 elements + padding + length - type QuadArray = ArrayVec<u32, 3>; + type QuadArray = ArrayVec<u32, 3>; println!("{}", mem::size_of::<QuadArray>()); assert!(mem::size_of::<QuadArray>() <= 4 * 4 + mem::size_of::<u32>()); } #[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<i32, 8> = 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::<DropPanic, 1>::new(); + let mut array = ArrayVec::<DropPanic, 1>::new(); array.push(DropPanic); } @@ -422,17 +422,17 @@ fn test_drop_panic_into_iter() { } } - let mut array = ArrayVec::<DropPanic, 1>::new(); + let mut array = ArrayVec::<DropPanic, 1>::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::<String, 4>::new(); + let mut v = ArrayVec::<String, 4>::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::<i32, 4>::new(); + let mut v = ArrayVec::<i32, 4>::new(); v.extend(1..=4); assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); } #[test] fn test_take() { - let mut v1 = ArrayVec::<i32, 4>::new(); + let mut v1 = ArrayVec::<i32, 4>::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::<String, 4>::new(); + let mut v = ArrayVec::<String, 4>::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<net::TcpStream, 4> = Default::default(); + let v: ArrayVec<net::TcpStream, 4> = 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]); @@ -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::<usize>() <= mem::size_of::<u32>() { - panic!("This test does not work on this platform. 'largest supported capacity'"); - } - // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); -} - -#[should_panic(expected="index out of bounds")] -#[test] -fn deny_max_capacity_arrayvec_value_const() { - if mem::size_of::<usize>() <= mem::size_of::<u32>() { - panic!("This test does not work on this platform. 'index out of bounds'"); - } - // this type is allowed to be used (but can't be constructed) - let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const(); -} - #[test] fn test_arrayvec_const_constructible() { const OF_U8: ArrayVec<Vec<u8>, 10> = ArrayVec::new_const();