#![no_std]
#![feature(const_generics)]
#![allow(incomplete_features)]
mod drain;
pub use drain::Drain;
use core::{
cmp::Ordering,
fmt::{self, Debug, Display, Formatter},
hash::{Hash, Hasher},
mem::{self, MaybeUninit},
ops::{Deref, DerefMut, Index, IndexMut, Range},
ptr, slice,
};
macro_rules! out_of_bounds {
($method:expr, $index:expr, $len:expr) => {
panic!(
concat!(
"ArrayVec::",
$method,
"(): index {} is out of bounds in vector of length {}"
),
$index, $len
);
};
}
pub struct ArrayVec<T, const N: usize> {
items: [MaybeUninit<T>; N],
length: usize,
}
impl<T, const N: usize> ArrayVec<T, { N }> {
pub fn new() -> ArrayVec<T, { N }> {
unsafe {
ArrayVec {
items: MaybeUninit::uninit().assume_init(),
length: 0,
}
}
}
pub const fn len(&self) -> usize { self.length }
pub const fn is_empty(&self) -> bool { self.len() == 0 }
pub const fn capacity(&self) -> usize { N }
pub const fn remaining_capacity(&self) -> usize {
self.capacity() - self.len()
}
pub const fn is_full(&self) -> bool { self.len() >= self.capacity() }
pub fn as_ptr(&self) -> *const T { self.items.as_ptr() as *const T }
pub fn as_mut_ptr(&mut self) -> *mut T { self.items.as_mut_ptr() as *mut T }
pub fn push(&mut self, item: T) {
match self.try_push(item) {
Ok(_) => {},
Err(e) => panic!("Push failed: {}", e),
}
}
pub fn try_push(&mut self, item: T) -> Result<(), CapacityError<T>> {
if self.is_full() {
Err(CapacityError(item))
} else {
unsafe {
self.push_unchecked(item);
Ok(())
}
}
}
pub unsafe fn push_unchecked(&mut self, item: T) {
debug_assert!(!self.is_full());
let len = self.len();
self.as_mut_ptr().add(len).write(item);
self.set_len(len + 1);
}
pub unsafe fn set_len(&mut self, new_length: usize) {
debug_assert!(new_length <= self.capacity());
self.length = new_length;
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
unsafe {
let new_length = self.len() - 1;
self.set_len(new_length);
Some(ptr::read(self.as_ptr().add(new_length)))
}
}
pub fn truncate(&mut self, new_length: usize) {
unsafe {
if new_length < self.len() {
let num_elements_to_remove = self.len() - new_length;
self.set_len(new_length);
let start = self.as_mut_ptr().add(new_length);
let tail: *mut [T] =
slice::from_raw_parts_mut(start, num_elements_to_remove);
ptr::drop_in_place(tail);
}
}
}
pub fn clear(&mut self) { self.truncate(0); }
pub fn insert(&mut self, index: usize, item: T) {
match self.try_insert(index, item) {
Ok(_) => {},
Err(e) => panic!("Insert failed: {}", e),
}
}
pub fn try_insert(
&mut self,
index: usize,
item: T,
) -> Result<(), CapacityError<T>> {
let len = self.len();
if index > self.len() {
out_of_bounds!("try_insert", index, len);
}
if self.is_full() {
return Err(CapacityError(item));
}
unsafe {
let p = self.as_mut_ptr().add(index);
ptr::copy(p, p.offset(1), len - index);
ptr::write(p, item);
self.set_len(len + 1);
}
Ok(())
}
pub fn as_slice(&self) -> &[T] { self.deref() }
pub fn as_slice_mut(&mut self) -> &mut [T] { self.deref_mut() }
pub fn try_extend_from_slice(
&mut self,
other: &[T],
) -> Result<(), CapacityError<()>>
where
T: Copy,
{
if self.remaining_capacity() < other.len() {
return Err(CapacityError(()));
}
let self_len = self.len();
let other_len = other.len();
unsafe {
let dst = self.as_mut_ptr().offset(self_len as isize);
ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len);
self.set_len(self_len + other_len);
}
Ok(())
}
pub fn drain(&mut self, range: Range<usize>) -> Drain<'_, T, { N }> {
Drain::with_range(self, range)
}
}
impl<T, const N: usize> Deref for ArrayVec<T, { N }> {
type Target = [T];
fn deref(&self) -> &Self::Target {
unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
}
}
impl<T, const N: usize> DerefMut for ArrayVec<T, { N }> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
}
}
impl<T, const N: usize> Drop for ArrayVec<T, { N }> {
fn drop(&mut self) {
self.clear();
}
}
impl<T, const N: usize> AsRef<[T]> for ArrayVec<T, { N }> {
fn as_ref(&self) -> &[T] { self.as_slice() }
}
impl<T, const N: usize> AsMut<[T]> for ArrayVec<T, { N }> {
fn as_mut(&mut self) -> &mut [T] { self.as_slice_mut() }
}
impl<T: Debug, const N: usize> Debug for ArrayVec<T, { N }> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.as_slice().fmt(f)
}
}
impl<T: PartialEq, const N: usize, const M: usize> PartialEq<ArrayVec<T, { M }>>
for ArrayVec<T, { N }>
{
fn eq(&self, other: &ArrayVec<T, { M }>) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: PartialEq, const N: usize> PartialEq<[T]> for ArrayVec<T, { N }> {
fn eq(&self, other: &[T]) -> bool { self.as_slice() == other }
}
impl<T: Eq, const N: usize> Eq for ArrayVec<T, { N }> {}
impl<T: PartialOrd, const N: usize> PartialOrd for ArrayVec<T, { N }> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<T: Ord, const N: usize> Ord for ArrayVec<T, { N }> {
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T: Hash, const N: usize> Hash for ArrayVec<T, { N }> {
fn hash<H: Hasher>(&self, hasher: &mut H) { self.as_slice().hash(hasher); }
}
impl<T, const N: usize> Default for ArrayVec<T, { N }> {
fn default() -> Self { ArrayVec::new() }
}
impl<Ix, T, const N: usize> Index<Ix> for ArrayVec<T, { N }>
where
[T]: Index<Ix>,
{
type Output = <[T] as Index<Ix>>::Output;
fn index(&self, ix: Ix) -> &Self::Output { self.as_slice().index(ix) }
}
impl<Ix, T, const N: usize> IndexMut<Ix> for ArrayVec<T, { N }>
where
[T]: IndexMut<Ix>,
{
fn index_mut(&mut self, ix: Ix) -> &mut Self::Output {
self.as_slice_mut().index_mut(ix)
}
}
impl<T: Clone, const N: usize> Clone for ArrayVec<T, { N }> {
fn clone(&self) -> ArrayVec<T, { N }> {
let mut other: ArrayVec<T, { N }> = ArrayVec::new();
for item in self.as_slice() {
unsafe {
other.push_unchecked(item.clone());
}
}
other
}
}
impl<T, const N: usize> From<[T; N]> for ArrayVec<T, { N }> {
fn from(other: [T; N]) -> ArrayVec<T, { N }> {
let mut vec = ArrayVec::<T, { N }>::new();
unsafe {
ptr::copy_nonoverlapping(
other.as_ptr(),
vec.as_mut_ptr(),
other.len(),
);
mem::forget(other);
vec.set_len(N);
}
vec
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CapacityError<T>(pub T);
impl<T> Display for CapacityError<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Insufficient capacity")
}
}
#[cfg(test)]
mod tests {
use super::ArrayVec;
#[test]
fn test_equal_to_expected_slice() {
let mut vector: ArrayVec<u8, 10> = ArrayVec::new();
vector.push(0);
vector.push(1);
vector.push(2);
assert_eq!(vector.len(), 3);
vector.try_insert(3, 3).unwrap();
assert_eq!(vector.as_slice(), &[0, 1, 2, 3]);
assert_eq!(vector.capacity(), 10);
}
}