use crate::{
len::{LengthType, Usize},
mem::{SpareMemoryPolicy, Uninitialized},
};
use core::{
marker::PhantomData,
mem,
ops::{Bound, RangeBounds},
ptr,
result::Result,
slice,
};
mod drain;
pub use drain::*;
pub mod errors;
use errors::*;
mod retain;
use retain::*;
pub struct ArrayVec<T, const C: usize, L = Usize, SM = Uninitialized>
where
L: LengthType,
SM: SpareMemoryPolicy<T>,
{
arr: [mem::MaybeUninit<T>; C],
len: L,
phantom1: PhantomData<SM>,
}
impl<T, L, SM, const C: usize> ArrayVec<T, C, L, SM>
where
L: LengthType,
SM: SpareMemoryPolicy<T>,
{
pub const CAPACITY: usize = C;
#[inline]
pub fn new() -> Self {
assert!(C <= L::MAX);
let mut v = ArrayVec {
arr: unsafe { mem::MaybeUninit::uninit().assume_init() },
len: L::new(0),
phantom1: PhantomData,
};
unsafe { SM::init(v.as_mut_ptr(), Self::CAPACITY) };
v
}
#[inline]
pub fn len(&self) -> usize {
self.len.as_usize()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn is_full(&self) -> bool {
self.len == Self::CAPACITY
}
#[inline]
pub fn as_ptr(&self) -> *const T {
self.arr.as_ptr() as *const T
}
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.arr.as_mut_ptr() as *mut T
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.as_ptr(), self.len.as_usize()) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len.as_usize()) }
}
#[inline]
pub fn capacity(&self) -> usize {
Self::CAPACITY
}
#[inline]
pub fn spare_capacity(&self) -> usize {
Self::CAPACITY - self.len.as_usize()
}
#[inline]
pub fn has_spare_capacity(&self) -> bool {
self.len < Self::CAPACITY
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= Self::CAPACITY);
self.len.set(new_len);
}
#[inline]
pub fn push(&mut self, e: T) {
if self.len >= Self::CAPACITY {
panic!("insufficient capacity");
}
unsafe { self.push_unchecked(e) };
}
#[inline]
pub fn try_push(&mut self, e: T) -> Result<(), InsufficientCapacityError> {
if self.len < Self::CAPACITY {
unsafe { self.push_unchecked(e) };
Ok(())
} else {
Err(InsufficientCapacityError {})
}
}
#[inline]
pub fn try_push_val(&mut self, value: T) -> Result<(), InsufficientCapacityErrorVal<T>> {
if self.len < Self::CAPACITY {
unsafe { self.push_unchecked(value) };
Ok(())
} else {
Err(InsufficientCapacityErrorVal(value))
}
}
#[inline]
pub unsafe fn push_unchecked(&mut self, value: T) {
let len = self.len();
self.as_mut_ptr().add(len).write(value);
self.set_len(len + 1);
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len > 0 {
unsafe { Some(self.pop_unchecked()) }
} else {
None
}
}
#[inline]
pub unsafe fn pop_unchecked(&mut self) -> T {
self.len -= 1;
let p = self.as_mut_ptr().add(self.len.as_usize());
let e = p.read();
SM::init(p, 1);
e
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0)
}
#[inline]
pub fn truncate(&mut self, len: usize) {
let my_len = self.len.as_usize();
if len < my_len {
unsafe {
self.set_len(len);
let s = slice::from_raw_parts_mut(self.as_mut_ptr().add(len), my_len - len);
ptr::drop_in_place(s);
SM::init(s.as_mut_ptr(), s.len());
}
}
}
#[inline]
pub fn iter(&self) -> slice::Iter<'_, T> {
self.as_slice().iter()
}
#[inline]
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
self.as_mut_slice().iter_mut()
}
#[inline]
pub fn try_from_iter<I>(iter: I) -> Result<Self, InsufficientCapacityError>
where
I: IntoIterator<Item = T>,
{
let mut tmp = Self::new();
let mut p = tmp.as_mut_ptr();
for e in iter {
if tmp.len >= Self::CAPACITY {
return Err(InsufficientCapacityError {});
}
unsafe {
p.write(e);
p = p.add(1);
tmp.len += 1;
}
}
Ok(tmp)
}
#[inline]
pub fn insert(&mut self, index: usize, element: T) {
self.try_insert(index, element).expect("cannot insert")
}
#[inline]
pub fn try_insert(&mut self, index: usize, value: T) -> Result<(), InsertError> {
let len = self.len();
if index > len {
return Err(InsertError::InvalidIndex);
}
if len >= Self::CAPACITY {
return Err(InsertError::InsufficientCapacity);
}
unsafe {
self.insert_unchecked(index, value);
}
Ok(())
}
#[inline]
pub fn try_insert_val(&mut self, index: usize, value: T) -> Result<(), InsertErrorVal<T>> {
if index > self.len.as_usize() {
return Err(InsertErrorVal::InvalidIndex(value));
}
if self.len >= Self::CAPACITY {
return Err(InsertErrorVal::InsufficientCapacity(value));
}
unsafe {
self.insert_unchecked(index, value);
}
Ok(())
}
#[inline]
pub unsafe fn insert_unchecked(&mut self, index: usize, value: T) {
let len = self.len();
let p = self.as_mut_ptr().add(index);
ptr::copy(p, p.add(1), len - index);
p.write(value);
self.set_len(len + 1);
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
if index >= self.len.as_usize() {
panic!("index is out of bounds [0, {}): {}", self.len, index);
}
unsafe { self.remove_unchecked(index) }
}
#[inline]
pub fn try_remove(&mut self, index: usize) -> Option<T> {
if index < self.len.as_usize() {
unsafe { Some(self.remove_unchecked(index)) }
} else {
None
}
}
#[inline]
pub unsafe fn remove_unchecked(&mut self, index: usize) -> T {
let base = self.as_mut_ptr();
let p = base.add(index);
let tmp = p.read();
ptr::copy(p.add(1), p, self.len.as_usize() - index - 1);
self.len -= 1;
SM::init(base.add(self.len.as_usize()), 1);
tmp
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
let len = self.len();
if index >= len {
panic!("index is out of bounds [0, {}): {}", len, index);
}
unsafe { self.swap_remove_unchecked(index) }
}
#[inline]
pub fn try_swap_remove(&mut self, index: usize) -> Option<T> {
if index < self.len.as_usize() {
unsafe { Some(self.swap_remove_unchecked(index)) }
} else {
None
}
}
#[inline]
pub unsafe fn swap_remove_unchecked(&mut self, index: usize) -> T {
let base = self.as_mut_ptr();
let p = base.add(index);
let value = p.read();
self.len -= 1;
let last = base.add(self.len.as_usize());
ptr::copy(last, p, 1);
SM::init(last, 1);
value
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T, L, SM, C>
where
R: RangeBounds<usize>,
{
let end = match range.end_bound() {
Bound::Included(e) => e
.checked_add(1)
.unwrap_or_else(|| panic!("end bound overflows")),
Bound::Excluded(e) => *e,
Bound::Unbounded => self.len(),
};
if end > self.len() {
panic!("invalid end bound");
}
let start = match range.start_bound() {
Bound::Included(s) => *s,
Bound::Excluded(s) => s
.checked_add(1)
.unwrap_or_else(|| panic!("start bound overflows")),
Bound::Unbounded => 0,
};
if start > end {
panic!("invalid range");
}
unsafe {
let len = self.len();
let (iter, tail, tail_len) = if start < end {
self.set_len(start);
(
slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start).iter(),
L::new(end),
L::new(len - end),
)
} else {
([].iter(), L::new(L::MAX), L::new(L::MAX))
};
Drain {
av: ptr::NonNull::new_unchecked(self),
iter,
tail,
tail_len,
}
}
}
#[inline]
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.retain_mut(|e| f(e))
}
#[inline]
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let len = self.len();
unsafe { self.set_len(0) };
let mut g = RetainGuard {
av: self,
len,
deleted: 0,
processed: 0,
};
unsafe {
while g.processed < len {
let item_mut_ref = &mut *g.av.as_mut_ptr().add(g.processed);
if !f(item_mut_ref) {
g.processed += 1;
g.deleted += 1;
ptr::drop_in_place(item_mut_ref);
break;
}
g.processed += 1;
}
while g.processed < len {
let base_p = g.av.as_mut_ptr();
let item_mut_ref = &mut *base_p.add(g.processed);
if !f(item_mut_ref) {
g.processed += 1;
g.deleted += 1;
ptr::drop_in_place(item_mut_ref);
continue;
} else {
ptr::copy_nonoverlapping(
item_mut_ref as *mut _,
base_p.add(g.processed - g.deleted),
1,
);
}
g.processed += 1;
}
}
}
#[inline]
pub fn spare_capacity_mut(&mut self) -> &mut [mem::MaybeUninit<T>] {
unsafe {
slice::from_raw_parts_mut(self.arr.as_mut_ptr().add(self.len()), self.spare_capacity())
}
}
#[inline]
pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [mem::MaybeUninit<T>]) {
let len = self.len();
let spare_capacity = self.spare_capacity();
let p = self.as_mut_ptr();
unsafe {
(
slice::from_raw_parts_mut(p, len),
slice::from_raw_parts_mut(p.add(len) as *mut mem::MaybeUninit<T>, spare_capacity),
)
}
}
#[inline]
pub fn resize_with<F>(&mut self, new_len: usize, f: F)
where
F: FnMut() -> T,
{
self.try_resize_with(new_len, f)
.expect("insufficient capacity")
}
#[inline]
pub fn try_resize_with<F>(
&mut self,
new_len: usize,
mut f: F,
) -> Result<(), InsufficientCapacityError>
where
F: FnMut() -> T,
{
if new_len > Self::CAPACITY {
return Err(InsufficientCapacityError {});
}
if new_len < self.len() {
self.truncate(new_len);
return Ok(());
}
while self.len() < new_len {
unsafe { self.push_unchecked(f()) };
}
Ok(())
}
}
impl<T, L, SM, const C: usize> ArrayVec<T, C, L, SM>
where
T: Clone,
L: LengthType,
SM: SpareMemoryPolicy<T>,
{
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
self.try_resize(new_len, value)
.expect("insufficient capacity");
}
pub fn try_resize(
&mut self,
new_len: usize,
value: T,
) -> Result<(), InsufficientCapacityError> {
if new_len > Self::CAPACITY {
return Err(InsufficientCapacityError {});
}
if new_len < self.len() {
self.truncate(new_len);
return Ok(());
}
while self.len() < new_len {
unsafe { self.push_unchecked(value.clone()) };
}
Ok(())
}
#[inline]
fn _clone_from(&mut self, other: &Self) {
unsafe {
self._clone_from_unchecked(other);
}
}
#[inline]
unsafe fn _clone_from_unchecked(&mut self, s: &[T]) {
debug_assert!(self.is_empty());
let mut p = self.as_mut_ptr();
for e in s {
p.write(e.clone());
p = p.add(1);
self.len += 1;
}
}
}
impl<T, L, SM, const C: usize> ArrayVec<T, C, L, SM>
where
T: Copy,
L: LengthType,
SM: SpareMemoryPolicy<T>,
{
#[inline]
pub fn copy_from_slice(&mut self, s: &[T]) {
if self.len() + s.len() > Self::CAPACITY {
panic!("insufficient capacity");
}
unsafe { self.copy_from_slice_unchecked(s) };
}
pub fn try_copy_from_slice(&mut self, s: &[T]) -> Result<(), InsufficientCapacityError> {
if self.len() + s.len() > Self::CAPACITY {
return Err(InsufficientCapacityError {});
}
unsafe { self.copy_from_slice_unchecked(s) };
Ok(())
}
#[inline]
pub unsafe fn copy_from_slice_unchecked(&mut self, s: &[T]) {
ptr::copy_nonoverlapping(s.as_ptr(), self.as_mut_ptr().add(self.len()), s.len());
self.len += s.len();
}
}
mod macros;
mod traits;
#[cfg(test)]
mod test_arrayvec;