#![no_std]
use core::iter::Peekable;
use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut};
use core::ptr;
#[derive(Debug)]
pub struct StackVec<T, const CAP: usize> {
inner: [MaybeUninit<T>; CAP],
length: usize,
}
impl<T, const CAP: usize> StackVec<T, CAP> {
#[inline]
pub const fn new() -> Self {
Self {
inner: [const { MaybeUninit::uninit() }; CAP ],
length: 0
}
}
#[inline(always)]
pub fn filled(val: T) -> Self
where
T: Clone
{
Self::generate(|| val.clone())
}
pub fn generate<Gen>(mut generator: Gen) -> Self
where
Gen: FnMut() -> T
{
let mut s = Self::new();
for _ in 0..CAP {
unsafe {
s.push_unchecked(generator());
}
}
s
}
pub const fn from_array(arr: [T; CAP]) -> Self {
let arr = ManuallyDrop::new(arr);
let inner = unsafe {
mem::transmute_copy(&arr)
};
Self { inner, length: CAP }
}
#[inline]
pub unsafe fn push_unchecked(&mut self, val: T) {
unsafe {
self.as_mut_ptr().add(self.length).write(val);
}
self.length += 1;
}
#[inline]
pub fn push(&mut self, val: T) {
if self.try_push(val).is_err() {
panic!("Attemp to push beyond the capacity of the array")
}
}
pub fn try_push(&mut self, val: T) -> Result<(),T> {
if self.length >= CAP {
Err(val)
} else {
unsafe { self.push_unchecked(val) };
Ok(())
}
}
#[inline]
pub fn extend_from_iter<I>(&mut self, it: I)
where
I: IntoIterator<Item = T>
{
for elem in it.into_iter() {
self.push(elem)
}
}
pub fn try_extend_from_iter<I>(&mut self, it: I) -> Result<(), Peekable<<I as IntoIterator>::IntoIter>>
where
I: IntoIterator<Item = T>
{
let mut it = it.into_iter().peekable();
while it.peek().is_some() {
if self.length >= CAP {
return Err(it)
}
unsafe {
let elem = it.next().unwrap_unchecked();
self.push_unchecked(elem)
}
}
Ok(())
}
pub unsafe fn remove_unchecked(&mut self, i: usize) -> T {
let ret = unsafe { self.inner[i].assume_init_read() };
let ptr = self.inner.as_mut_ptr();
unsafe {
ptr::copy(
ptr.add(i + 1),
ptr.add(i),
self.length - i - 1
);
}
self.length -= 1;
ret
}
pub fn remove(&mut self, i: usize) -> Option<T> {
if i <= self.length {
unsafe { Some(self.remove_unchecked(i)) }
} else {
None
}
}
#[inline(always)]
pub fn pop(&mut self) -> Option<T> {
self.remove(self.length)
}
pub const fn as_slice(&self) -> &[T] {
let (slice, _) = self.inner.split_at(self.length);
unsafe {
mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
}
}
pub const fn as_slice_mut(&mut self) -> &mut [T] {
let (slice, _) = self.inner.split_at_mut(self.length);
unsafe {
mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice)
}
}
#[inline(always)]
pub const fn as_ptr(&self) -> *const T {
self.inner.as_ptr() as *const T
}
#[inline(always)]
pub const fn as_mut_ptr(&mut self) -> *mut T {
self.inner.as_mut_ptr() as *mut T
}
#[inline(always)]
pub const fn capacity(&self) -> usize { CAP }
#[inline(always)]
pub const fn remaining_capacity(&self) -> usize { CAP - self.length }
#[inline(always)]
pub const fn len(&self) -> usize { self.length }
#[inline(always)]
pub const fn is_empty(&self) -> bool { self.length == 0 }
#[inline(always)]
pub const fn is_full(&self) -> bool { self.length == CAP }
}
impl<T, const CAP: usize> Deref for StackVec<T, CAP> {
type Target = [T];
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T, const CAP: usize> DerefMut for StackVec<T, CAP> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut [T] {
self.as_slice_mut()
}
}
impl<T, const CAP: usize> Default for StackVec<T, CAP> {
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
impl<T, const CAP: usize> From<[T; CAP]> for StackVec<T, CAP> {
#[inline(always)]
fn from(value: [T; CAP]) -> Self {
StackVec::from_array(value)
}
}
impl<T, const CAP: usize> Drop for StackVec<T, CAP> {
fn drop(&mut self) {
if mem::needs_drop::<T>() {
for elem in &mut self.inner[0..self.length] {
unsafe {
elem.assume_init_drop();
}
}
}
}
}
impl<T: Clone, const CAP: usize> Clone for StackVec<T, CAP> {
fn clone(&self) -> Self {
let mut inner = [const { MaybeUninit::uninit() }; CAP];
let src = self.inner.as_ptr();
let dst = inner.as_mut_ptr();
unsafe { ptr::copy(src, dst, self.length); }
Self {
inner,
length: self.length,
}
}
}
impl<T: PartialEq, const CAP: usize> PartialEq for StackVec<T, CAP> {
fn eq(&self, other: &Self) -> bool {
self.as_slice().iter().eq(other.as_slice().iter())
}
}
impl<T: PartialOrd, const CAP: usize> PartialOrd for StackVec<T, CAP> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.as_slice().iter().partial_cmp(other.as_slice().iter())
}
}