no_std_collections 0.1.1

Auxiliary structures and traits for using dynamically resizable arrays (Vectors) in flexible environments, supporting both std and no_std contexts.
Documentation
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()
    }
}