From c9b095f26328e08e4f9dae34897b39ea6f4145a4 Mon Sep 17 00:00:00 2001 From: bluss Date: Tue, 23 Mar 2021 17:31:27 +0100 Subject: [PATCH] FEAT: Port ArrayString to const generics --- src/array_string.rs | 193 +++++++++++++++++++------------------------- src/arrayvec.rs | 3 - src/lib.rs | 3 - src/maybe_uninit.rs | 44 ---------- 4 files changed, 84 insertions(+), 159 deletions(-) delete mode 100644 src/maybe_uninit.rs diff --git a/src/array_string.rs b/src/array_string.rs index 48139b2..d8dc6ac 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -3,6 +3,7 @@ use std::cmp; use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; +use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; use std::ptr; use std::slice; @@ -10,16 +11,12 @@ use std::str; use std::str::FromStr; use std::str::Utf8Error; -use crate::array::Array; -use crate::array::Index; use crate::CapacityError; use crate::char::encode_utf8; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; -use super::MaybeUninit as MaybeUninitCopy; - /// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track @@ -28,24 +25,21 @@ use super::MaybeUninit as MaybeUninitCopy; /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] -pub struct ArrayString - where A: Array + Copy -{ - xs: MaybeUninitCopy, - len: A::Index, +pub struct ArrayString { + // the `len` first elements of the array are initialized + xs: [MaybeUninit; CAP], + len: usize, } -impl Default for ArrayString - where A: Array + Copy +impl Default for ArrayString { /// Return an empty `ArrayString` - fn default() -> ArrayString { + fn default() -> ArrayString { ArrayString::new() } } -impl ArrayString - where A: Array + Copy +impl ArrayString { /// Create a new empty `ArrayString`. /// @@ -54,34 +48,28 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 16]>::new(); + /// let mut string = ArrayString::<16>::new(); /// string.push_str("foo"); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` #[cfg(not(feature="unstable-const-fn"))] - pub fn new() -> ArrayString { + pub fn new() -> ArrayString { unsafe { - ArrayString { - xs: MaybeUninitCopy::uninitialized(), - len: Index::ZERO, - } + ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } #[cfg(feature="unstable-const-fn")] - pub const fn new() -> ArrayString { + pub const fn new() -> ArrayString { unsafe { - ArrayString { - xs: MaybeUninitCopy::uninitialized(), - len: Index::ZERO, - } + ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } /// Return the length of the string. #[inline] - pub fn len(&self) -> usize { self.len.to_usize() } + pub fn len(&self) -> usize { self.len } /// Returns whether the string is empty. #[inline] @@ -96,7 +84,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut string = ArrayString::<3>::from("foo").unwrap(); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.len(), 3); /// assert_eq!(string.capacity(), 3); @@ -116,13 +104,16 @@ impl ArrayString /// /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); /// ``` - pub fn from_byte_string(b: &A) -> Result { - let len = str::from_utf8(b.as_slice())?.len(); - debug_assert_eq!(len, A::CAPACITY); - Ok(ArrayString { - xs: MaybeUninitCopy::from(*b), - len: Index::from(A::CAPACITY), - }) + pub fn from_byte_string(b: &[u8; CAP]) -> Result { + let len = str::from_utf8(b)?.len(); + debug_assert_eq!(len, CAP); + let mut vec = Self::new(); + unsafe { + (b as *const [u8; CAP] as *const [MaybeUninit; CAP]) + .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); + vec.set_len(CAP); + } + Ok(vec) } /// Return the capacity of the `ArrayString`. @@ -130,18 +121,18 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let string = ArrayString::<[_; 3]>::new(); + /// let string = ArrayString::<3>::new(); /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] - pub fn capacity(&self) -> usize { A::CAPACITY } + pub fn capacity(&self) -> usize { CAP } /// Return if the `ArrayString` is completely filled. /// /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 1]>::new(); + /// let mut string = ArrayString::<1>::new(); /// assert!(!string.is_full()); /// string.push_str("A"); /// assert!(string.is_full()); @@ -155,7 +146,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.push('a'); /// string.push('b'); @@ -175,7 +166,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.try_push('a').unwrap(); /// string.try_push('b').unwrap(); @@ -187,7 +178,7 @@ impl ArrayString pub fn try_push(&mut self, c: char) -> Result<(), CapacityError> { let len = self.len(); unsafe { - let ptr = self.xs.ptr_mut().add(len); + let ptr = self.as_mut_ptr().add(len); let remaining_cap = self.capacity() - len; match encode_utf8(c, ptr, remaining_cap) { Ok(n) => { @@ -206,7 +197,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.push_str("a"); /// string.push_str("d"); @@ -226,7 +217,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 2]>::new(); + /// let mut string = ArrayString::<2>::new(); /// /// string.try_push_str("a").unwrap(); /// let overflow1 = string.try_push_str("bc"); @@ -242,7 +233,7 @@ impl ArrayString return Err(CapacityError::new(s)); } unsafe { - let dst = self.xs.ptr_mut().add(self.len()); + let dst = self.as_mut_ptr().add(self.len()); let src = s.as_ptr(); ptr::copy_nonoverlapping(src, dst, s.len()); let newl = self.len() + s.len(); @@ -258,7 +249,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); @@ -288,7 +279,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut string = ArrayString::<[_; 6]>::from("foobar").unwrap(); + /// let mut string = ArrayString::<6>::from("foobar").unwrap(); /// string.truncate(3); /// assert_eq!(&string[..], "foo"); /// string.truncate(4); @@ -318,7 +309,7 @@ impl ArrayString /// ``` /// use arrayvec::ArrayString; /// - /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); @@ -333,8 +324,8 @@ impl ArrayString let next = idx + ch.len_utf8(); let len = self.len(); unsafe { - ptr::copy(self.xs.ptr().add(next), - self.xs.ptr_mut().add(idx), + ptr::copy(self.as_ptr().add(next), + self.as_mut_ptr().add(idx), len - next); self.set_len(len - (next - idx)); } @@ -357,103 +348,99 @@ impl ArrayString /// and may use other debug assertions. pub unsafe fn set_len(&mut self, length: usize) { debug_assert!(length <= self.capacity()); - self.len = Index::from(length); + self.len = length; } /// Return a string slice of the whole `ArrayString`. pub fn as_str(&self) -> &str { self } + + fn as_ptr(&self) -> *const u8 { + self.xs.as_ptr() as *const u8 + } + + fn as_mut_ptr(&mut self) -> *mut u8 { + self.xs.as_mut_ptr() as *mut u8 + } } -impl Deref for ArrayString - where A: Array + Copy +impl Deref for ArrayString { type Target = str; #[inline] fn deref(&self) -> &str { unsafe { - let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize()); + let sl = slice::from_raw_parts(self.as_ptr(), self.len); str::from_utf8_unchecked(sl) } } } -impl DerefMut for ArrayString - where A: Array + Copy +impl DerefMut for ArrayString { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { - let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize()); + let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len); str::from_utf8_unchecked_mut(sl) } } } -impl PartialEq for ArrayString - where A: Array + Copy +impl PartialEq for ArrayString { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } -impl PartialEq for ArrayString - where A: Array + Copy +impl PartialEq for ArrayString { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } -impl PartialEq> for str - where A: Array + Copy +impl PartialEq> for str { - fn eq(&self, rhs: &ArrayString) -> bool { + fn eq(&self, rhs: &ArrayString) -> bool { self == &**rhs } } -impl Eq for ArrayString - where A: Array + Copy +impl Eq for ArrayString { } -impl Hash for ArrayString - where A: Array + Copy +impl Hash for ArrayString { fn hash(&self, h: &mut H) { (**self).hash(h) } } -impl Borrow for ArrayString - where A: Array + Copy +impl Borrow for ArrayString { fn borrow(&self) -> &str { self } } -impl AsRef for ArrayString - where A: Array + Copy +impl AsRef for ArrayString { fn as_ref(&self) -> &str { self } } -impl fmt::Debug for ArrayString - where A: Array + Copy +impl fmt::Debug for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } -impl fmt::Display for ArrayString - where A: Array + Copy +impl fmt::Display for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } /// `Write` appends written data to the end of the string. -impl fmt::Write for ArrayString - where A: Array + Copy +impl fmt::Write for ArrayString { fn write_char(&mut self, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error) @@ -464,10 +451,9 @@ impl fmt::Write for ArrayString } } -impl Clone for ArrayString - where A: Array + Copy +impl Clone for ArrayString { - fn clone(&self) -> ArrayString { + fn clone(&self) -> ArrayString { *self } fn clone_from(&mut self, rhs: &Self) { @@ -477,8 +463,7 @@ impl Clone for ArrayString } } -impl PartialOrd for ArrayString - where A: Array + Copy +impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &Self) -> Option { (**self).partial_cmp(&**rhs) @@ -489,8 +474,7 @@ impl PartialOrd for ArrayString fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } } -impl PartialOrd for ArrayString - where A: Array + Copy +impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &str) -> Option { (**self).partial_cmp(rhs) @@ -501,28 +485,25 @@ impl PartialOrd for ArrayString fn ge(&self, rhs: &str) -> bool { &**self >= rhs } } -impl PartialOrd> for str - where A: Array + Copy +impl PartialOrd> for str { - fn partial_cmp(&self, rhs: &ArrayString) -> Option { + fn partial_cmp(&self, rhs: &ArrayString) -> Option { self.partial_cmp(&**rhs) } - fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } - fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } - fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } - fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } + fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } + fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } + fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } + fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } } -impl Ord for ArrayString - where A: Array + Copy +impl Ord for ArrayString { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } -impl FromStr for ArrayString - where A: Array + Copy +impl FromStr for ArrayString { type Err = CapacityError; @@ -533,8 +514,7 @@ impl FromStr for ArrayString #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl Serialize for ArrayString - where A: Array + Copy +impl Serialize for ArrayString { fn serialize(&self, serializer: S) -> Result where S: Serializer @@ -545,8 +525,7 @@ impl Serialize for ArrayString #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<'de, A> Deserialize<'de> for ArrayString - where A: Array + Copy +impl<'de, const CAP: usize> Deserialize<'de> for ArrayString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> @@ -554,13 +533,13 @@ impl<'de, A> Deserialize<'de> for ArrayString use serde::de::{self, Visitor}; use std::marker::PhantomData; - struct ArrayStringVisitor>(PhantomData); + struct ArrayStringVisitor(PhantomData([u8; CAP])); - impl<'de, A: Copy + Array> Visitor<'de> for ArrayStringVisitor { - type Value = ArrayString; + impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor { + type Value = ArrayString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a string no more than {} bytes long", A::CAPACITY) + write!(formatter, "a string no more than {} bytes long", CAP) } fn visit_str(self, v: &str) -> Result @@ -578,13 +557,11 @@ impl<'de, A> Deserialize<'de> for ArrayString } } - deserializer.deserialize_str(ArrayStringVisitor::(PhantomData)) + deserializer.deserialize_str(ArrayStringVisitor(PhantomData)) } } -impl<'a, A> TryFrom<&'a str> for ArrayString -where - A: Array + Copy +impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString { type Error = CapacityError<&'a str>; @@ -595,9 +572,7 @@ where } } -impl<'a, A> TryFrom> for ArrayString -where - A: Array + Copy +impl<'a, const CAP: usize> TryFrom> for ArrayString { type Error = CapacityError; diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 680020e..d58ebc2 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -17,9 +17,6 @@ use std::io; use std::mem::ManuallyDrop; use std::mem::MaybeUninit; -//use crate::maybe_uninit::MaybeUninit; - - #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; diff --git a/src/lib.rs b/src/lib.rs index 2d21aa2..cfd1515 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,9 +34,6 @@ extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; -mod maybe_uninit; -use crate::maybe_uninit::MaybeUninit; - #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; diff --git a/src/maybe_uninit.rs b/src/maybe_uninit.rs deleted file mode 100644 index e009abf..0000000 --- a/src/maybe_uninit.rs +++ /dev/null @@ -1,44 +0,0 @@ - - -use crate::array::Array; -use std::mem::MaybeUninit as StdMaybeUninit; - -#[derive(Copy)] -pub struct MaybeUninit { - inner: StdMaybeUninit, -} - -impl Clone for MaybeUninit - where T: Copy -{ - fn clone(&self) -> Self { *self } -} - -impl MaybeUninit { - /// Create a new MaybeUninit with uninitialized interior - pub const unsafe fn uninitialized() -> Self { - MaybeUninit { inner: StdMaybeUninit::uninit() } - } - - /// Create a new MaybeUninit from the value `v`. - pub fn from(v: T) -> Self { - MaybeUninit { inner: StdMaybeUninit::new(v) } - } - - // Raw pointer casts written so that we don't reference or access the - // uninitialized interior value - - /// Return a raw pointer to the start of the interior array - pub fn ptr(&self) -> *const T::Item - where T: Array - { - self.inner.as_ptr() as *const T::Item - } - - /// Return a mut raw pointer to the start of the interior array - pub fn ptr_mut(&mut self) -> *mut T::Item - where T: Array - { - self.inner.as_mut_ptr() as *mut T::Item - } -}