#![forbid(unused_must_use)] #![feature(array_into_iter_constructors)] #![feature(const_intrinsic_copy)] #![feature(const_maybe_uninit_assume_init)] #![feature(const_maybe_uninit_uninit_array)] #![feature(const_mut_refs)] #![feature(const_option)] #![feature(const_refs_to_cell)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_split_at_mut)] #![feature(const_trait_impl)] #![feature(effects)] #![feature(generic_const_exprs)] #![feature(iter_repeat_n)] #![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] #![feature(new_uninit)] #![feature(slice_index_methods)] #![feature(split_array)] use std::fmt::{Debug, Display}; use std::hash::Hash; use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; #[derive(Copy)] pub struct ArrayVec { data: [MaybeUninit; N], /// Do not ever modify this field directly. Use [`Self::set_len`] instead. len: usize, } // impl ArrayVec { // pub const EMPTY: ArrayVec = Self::new(); // } #[inline(always)] const unsafe fn slice_unchecked(slice: &[T], offset: usize, len: Option) -> &[T] { std::slice::from_raw_parts( slice.as_ptr().add(offset), match len { Some(t) => t, None => slice.len() - offset, }, ) } #[inline(always)] const unsafe fn slice_unchecked_mut( slice: &mut [T], offset: usize, len: Option, ) -> &mut [T] { std::slice::from_raw_parts_mut( slice.as_mut_ptr().add(offset), match len { Some(t) => t, None => slice.len() - offset, }, ) } impl ArrayVec { #[inline] pub const fn new() -> Self { Self { data: MaybeUninit::uninit_array(), len: 0, } } #[inline] pub const fn as_slice(&self) -> &[T] { unsafe { MaybeUninit::slice_assume_init_ref(slice_unchecked(&self.data, 0, Some(self.len))) } } #[inline] pub const fn as_slice_mut(&mut self) -> &mut [T] { unsafe { MaybeUninit::slice_assume_init_mut(slice_unchecked_mut( &mut self.data, 0, Some(self.len), )) } } #[inline] pub const fn as_ptr(&self) -> *const T { MaybeUninit::slice_as_ptr(&self.data) } #[inline] pub const fn as_mut_ptr(&mut self) -> *mut T { MaybeUninit::slice_as_mut_ptr(&mut self.data) } #[inline] pub fn iter(&self) -> std::slice::Iter { (**self).iter() } #[inline] pub fn iter_mut(&mut self) -> std::slice::IterMut { (**self).iter_mut() } #[inline(always)] pub const fn len(&self) -> usize { self.len } #[inline(always)] pub const fn unused(&self) -> &[MaybeUninit] { unsafe { slice_unchecked(&self.data, self.len, None) } } #[inline(always)] pub const fn unused_mut(&mut self) -> &mut [MaybeUninit] { unsafe { slice_unchecked_mut(&mut self.data, self.len, None) } } /// # Safety /// /// - `new_len` must be less than or equal to `N`. /// - The elements at `0..new_len` must be initialized. In practice, this can be reduced to `old_len..new_len`. #[inline(always)] pub const unsafe fn set_len(&mut self, len: usize) { debug_assert!(len <= N); self.len = len; } /// # Panics /// /// This function will panic if there is not sufficient spare capacity for the entire `slice`. #[inline] pub const fn push_slice(&mut self, slice: &[T]) where T: Copy, { assert!(slice.len() <= self.unused().len()); let old_len = self.len(); let (_, unused) = self.data.split_at_mut(old_len); unsafe { MaybeUninit::slice_as_mut_ptr(unused) .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); self.set_len(old_len + slice.len()); } } #[inline] pub const fn from(value: [T; N]) -> Self { Self { len: value.len(), data: MaybeUninit::transpose(MaybeUninit::new(value)), } } } impl Clone for ArrayVec { #[inline] fn clone(&self) -> Self { let mut new = Self::new(); self.as_slice() .iter() .zip(&mut new.data[0..self.len]) .for_each(|(src, dst)| *dst = MaybeUninit::new(src.clone())); unsafe { new.set_len(self.len) }; new } #[inline] fn clone_from(&mut self, source: &Self) { source .as_slice() .iter() .zip(&mut self.data[0..self.len]) .for_each(|(src, dst)| *dst = MaybeUninit::new(src.clone())); unsafe { self.set_len(source.len) }; } } impl PartialEq for ArrayVec { #[inline] fn eq(&self, other: &Self) -> bool { self.as_slice() == other.as_slice() } } impl Eq for ArrayVec {} impl PartialOrd for ArrayVec { #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.as_slice().partial_cmp(other.as_slice()) } } impl Ord for ArrayVec { #[inline] fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_slice().cmp(other.as_slice()) } } impl Hash for ArrayVec { #[inline] fn hash(&self, state: &mut H) { self.as_slice().hash(state) } } impl IntoIterator for ArrayVec { type Item = T; type IntoIter = std::array::IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { unsafe { std::array::IntoIter::new_unchecked(self.data, 0..self.len) } } } impl Debug for ArrayVec { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_list().entries(self.iter()).finish() } } impl Deref for ArrayVec { type Target = [T]; #[inline] fn deref(&self) -> &Self::Target { self.as_slice() } } impl DerefMut for ArrayVec { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_slice_mut() } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct ArrayStr(ArrayVec); // impl ArrayStr<0> { // pub const EMPTY: ArrayStr<0> = Self::new(); // } impl ArrayStr { #[inline] pub const fn new() -> Self { Self(ArrayVec::new()) } #[inline(always)] pub const fn from_utf8(bytes: ArrayVec) -> Result { if let Err(e) = std::str::from_utf8(bytes.as_slice()) { return Err(e); } Ok(Self(bytes)) } #[inline] pub const unsafe fn from_utf8_unchecked(bytes: ArrayVec) -> Self { if cfg!(debug_assertions) { match Self::from_utf8(bytes) { Ok(t) => t, Err(_) => panic!(), } } else { Self(bytes) } } pub const fn data(&self) -> &ArrayVec { &self.0 } pub const fn data_mut(&mut self) -> &mut ArrayVec { &mut self.0 } pub const fn into_data(self) -> ArrayVec { self.0 } #[inline] pub const fn as_str(&self) -> &str { unsafe { std::str::from_utf8_unchecked(&self.0) } } #[inline] pub fn as_mut_str(&mut self) -> &mut str { unsafe { std::str::from_utf8_unchecked_mut(&mut self.0) } } #[inline] pub const fn as_ptr(&self) -> *const u8 { self.0.as_ptr() } #[inline] pub const fn as_mut_ptr(&mut self) -> *mut u8 { self.0.as_mut_ptr() } /// # Panics /// /// This function will panic if there is not sufficient spare capacity for the entire `string`. #[inline] pub const fn push_str(&mut self, string: &str) { self.0.push_slice(string.as_bytes()) } #[inline] pub fn push(&mut self, character: char) -> Result<(), PushCharError> { let len = character.len_utf8(); let unused = self.0.unused_mut(); if len <= unused.len() { let unused = &mut unused[0..len]; unused.fill(MaybeUninit::new(0)); // SAFETY: the first `len` bytes have been initialized. let unused = unsafe { MaybeUninit::slice_assume_init_mut(unused) }; character.encode_utf8(unused); unsafe { self.0.set_len(len) }; Ok(()) } else { Err(PushCharError { unused_len: unused.len(), character, }) } } } impl Deref for ArrayStr { type Target = str; #[inline] fn deref(&self) -> &Self::Target { self.as_str() } } impl DerefMut for ArrayStr { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_str() } } impl AsRef for ArrayStr { #[inline] fn as_ref(&self) -> &str { self } } impl AsMut for ArrayStr { #[inline] fn as_mut(&mut self) -> &mut str { self } } impl Debug for ArrayStr { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) } } impl Display for ArrayStr { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } } impl From<[T; N]> for ArrayVec { #[inline] fn from(value: [T; N]) -> Self { Self::from(value) } } #[derive(Debug, Clone, Copy)] pub struct TryFromSliceError { max_len: usize, slice_len: usize, } impl Display for TryFromSliceError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("The slice, with length ")?; write!(f, "{}", self.slice_len)?; f.write_str(", is too long for the type, with maximum length ")?; write!(f, "{}", self.max_len)?; Ok(()) } } impl std::error::Error for TryFromSliceError {} #[derive(Debug, Clone, Copy)] pub struct PushCharError { unused_len: usize, character: char, } impl Display for PushCharError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use std::fmt::Write; f.write_str("The code point ")?; for c in self.character.escape_debug() { f.write_char(c)?; } f.write_str(", with UTF-8 length ")?; write!(f, "{}", self.character.len_utf8())?; f.write_str(", is too long for the type, with maximum length ")?; write!(f, "{}", self.unused_len)?; Ok(()) } } impl std::error::Error for PushCharError {} impl<'a, T: Copy, const N: usize> ArrayVec { #[inline(always)] pub const fn try_from(value: &'a [T]) -> Result { if value.len() > N { return Err(TryFromSliceError { slice_len: value.len(), max_len: N, }); } let mut vec = Self::new(); unsafe { MaybeUninit::slice_as_mut_ptr(&mut vec.data) .copy_from_nonoverlapping(value.as_ptr(), value.len()); vec.set_len(value.len()); } Ok(vec) } } impl<'a, T: Copy, const N: usize> TryFrom<&'a [T]> for ArrayVec { type Error = TryFromSliceError; #[inline(always)] fn try_from(value: &'a [T]) -> Result { Self::try_from(value) } } impl<'a, const N: usize> ArrayStr { #[inline(always)] pub const fn try_from(value: &'a str) -> Result { match ArrayVec::try_from(value.as_bytes()) { Ok(t) => Ok(Self(t)), Err(e) => Err(e), } } } impl<'a, const N: usize> TryFrom<&'a str> for ArrayStr { type Error = TryFromSliceError; #[inline(always)] fn try_from(value: &'a str) -> Result { Self::try_from(value) } } impl<'a, const N: usize> TryFrom for ArrayStr { type Error = PushCharError; #[inline] fn try_from(value: char) -> Result { let mut arr = Self::new(); arr.push(value)?; Ok(arr) } } // impl ArrayVec { // pub const fn concat(self, rhs: ArrayVec) -> ArrayVec // where // [(); N + M]:, // { // let mut new = ArrayVec::::new(); // let mut i = 0; // while i < self.len { // new.data[i] = unsafe { MaybeUninit::new(self.data[i].assume_init_read()) }; // i += 1; // } // let mut j = 0; // while j < rhs.len { // new.data[i] = unsafe { MaybeUninit::new(rhs.data[j].assume_init_read()) }; // i += 1; // j += 1; // } // unsafe { new.set_len(self.len + rhs.len) }; // new // } // } // impl ArrayStr { // pub const fn concat(self, rhs: ArrayStr) -> ArrayStr<{ N + M }> // where // [(); N + M]:, // { // ArrayStr(self.0.concat(rhs.0)) // } // } #[cfg(test)] mod tests { use crate::ArrayVec; const _FOO: ArrayVec<(), 4> = ArrayVec::from([(), (), (), ()]); const _FOO_LEN: usize = _FOO.as_slice().len(); const _FOO_UNUSED: usize = _FOO.unused().len(); }