diff --git a/src/lib.rs b/src/lib.rs index 8bf16d5..fa44c6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ #![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)] @@ -23,7 +24,6 @@ use std::fmt::{Debug, Display}; use std::hash::Hash; use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; -use std::slice::SliceIndex; #[derive(Copy)] pub struct ArrayVec { @@ -36,6 +36,32 @@ pub struct 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 { @@ -48,14 +74,19 @@ impl ArrayVec { #[inline] pub const fn as_slice(&self) -> &[T] { unsafe { - MaybeUninit::slice_assume_init_ref(&*(0..self.len).get_unchecked(self.data.as_slice())) + MaybeUninit::slice_assume_init_ref(slice_unchecked(&self.data, 0, Some(self.len))) } } #[inline] pub const fn as_slice_mut(&mut self) -> &mut [T] { - let slice: &mut [MaybeUninit] = &mut self.data; - unsafe { MaybeUninit::slice_assume_init_mut(&mut *(0..self.len).get_unchecked_mut(slice)) } + unsafe { + MaybeUninit::slice_assume_init_mut(slice_unchecked_mut( + &mut self.data, + 0, + Some(self.len), + )) + } } #[inline] @@ -85,13 +116,12 @@ impl ArrayVec { #[inline(always)] pub const fn unused(&self) -> &[MaybeUninit] { - unsafe { &*(self.len..).get_unchecked(self.data.as_slice()) } + unsafe { slice_unchecked(&self.data, self.len, None) } } #[inline(always)] pub const fn unused_mut(&mut self) -> &mut [MaybeUninit] { - let slice: &mut [MaybeUninit] = &mut self.data; - unsafe { &mut *(self.len..).get_unchecked_mut(slice) } + unsafe { slice_unchecked_mut(&mut self.data, self.len, None) } } /// # Safety @@ -121,6 +151,14 @@ impl ArrayVec { 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 { @@ -352,10 +390,7 @@ impl Display for ArrayStr { impl From<[T; N]> for ArrayVec { #[inline] fn from(value: [T; N]) -> Self { - Self { - len: value.len(), - data: MaybeUninit::transpose(MaybeUninit::new(value)), - } + Self::from(value) } } @@ -488,3 +523,12 @@ impl<'a, const N: usize> TryFrom for ArrayStr { // 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(); +}