use core::fmt;
use vec::Vec;
use crate::traits::*;
pub struct StackVec<T, const N: usize> {
buff: [T; N],
len: usize,
}
impl<T, const N: usize> StackVec<T, N> {
const IS_ZST: bool = core::mem::size_of::<T>() == 0;
const UNINIT_ITEM: T = unsafe { core::mem::MaybeUninit::uninit().assume_init() };
const UNINIT_ARRAY: [T; N] = [Self::UNINIT_ITEM; N];
pub const fn new() -> Self {
Self {
buff: Self::UNINIT_ARRAY,
len: 0,
}
}
}
impl<T, const N: usize> From<[T; N]> for StackVec<T, N> {
fn from(value: [T; N]) -> Self {
Self {
buff: value,
len: N,
}
}
}
impl<T, const N: usize> IntoIterator for StackVec<T, N> {
type Item = T;
type IntoIter = IntoIter<T, N>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
array: self.buff,
start: 0,
end: self.len,
}
}
}
unsafe impl<T, const N: usize> SliceOwner for StackVec<T, N> {
#[inline(always)]
fn len(&self) -> usize {
self.len
}
#[inline(always)]
fn as_ptr(&self) -> *const Self::Item {
self.buff.as_ptr()
}
#[inline(always)]
fn as_mut_ptr(&mut self) -> *mut Self::Item {
self.buff.as_mut_ptr()
}
}
unsafe impl<T, const N: usize> Vec for StackVec<T, N> {
fn capacity(&self) -> usize {
if Self::IS_ZST {
usize::MAX
} else {
N
}
}
unsafe fn set_len(&mut self, new_len: usize) {
self.len = new_len;
}
fn reserve(&mut self, _: usize) {
panic!("Can not reserve in a StackVec!")
}
unsafe fn split_off_unchecked(&mut self, at: usize) -> Self {
let other_len = self.len().unchecked_sub(at);
let mut other = Self {
buff: Self::UNINIT_ARRAY,
len: other_len,
};
unsafe {
self.set_len(at);
self.as_ptr()
.add(at)
.copy_to_nonoverlapping(other.as_mut_ptr(), other_len);
}
other
}
}
impl<T, const N: usize> FromIterator<T> for StackVec<T, N> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut this = Self::new();
for item in iter {
Vec::push(&mut this, item);
}
this
}
}
pub struct IntoIter<T, const N: usize> {
array: [T; N],
start: usize,
end: usize,
}
impl<T, const N: usize> Default for IntoIter<T, N> {
fn default() -> Self {
Self {
array: StackVec::UNINIT_ARRAY,
start: 0,
end: 0,
}
}
}
impl<T, const N: usize> IntoIter<T, N> {
#[inline(always)]
pub fn new(vec: StackVec<T, N>) -> Self {
vec.into_iter()
}
#[inline(always)]
pub fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.array.as_ptr().add(self.start), self.len()) }
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe {
core::slice::from_raw_parts_mut(self.array.as_mut_ptr().add(self.start), self.len())
}
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.end > self.start {
let curr = self.start;
self.start = unsafe { curr.unchecked_add(1) };
Some(unsafe { self.array.as_ptr().add(curr).read() })
} else {
None
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
#[inline(always)]
fn count(self) -> usize {
self.len()
}
#[inline(always)]
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
}
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.end > self.start {
let curr = self.end;
self.end = unsafe { curr.unchecked_sub(1) };
Some(unsafe { self.array.as_ptr().add(curr).read() })
} else {
None
}
}
}
impl<T, const N: usize> Drop for IntoIter<T, N> {
#[inline(always)]
fn drop(&mut self) {
unsafe { core::ptr::drop_in_place(self.as_mut_slice()) }
}
}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
#[inline(always)]
fn len(&self) -> usize {
unsafe { self.end.unchecked_sub(self.start) }
}
}
impl<T, const N: usize> core::iter::FusedIterator for IntoIter<T, N> {}
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
fn clone(&self) -> Self {
let mut new = StackVec::<T, N>::UNINIT_ARRAY;
let ptr = new.as_mut_ptr();
for index in self.start..self.end {
unsafe {
ptr.add(index)
.write(self.array.get_unchecked(index).clone())
};
}
Self {
array: new,
start: self.start,
end: self.end,
}
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
}
}