use std::borrow::{Borrow, BorrowMut};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::mem::{ManuallyDrop, MaybeUninit};
use std::ops::{
Bound, Deref, DerefMut, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull,
RangeInclusive, RangeTo, RangeToInclusive,
};
use std::ptr::NonNull;
use std::{fmt, ptr, slice};
type Size = u32;
macro_rules! assert_capacity {
($cap: expr) => {
if std::mem::size_of::<usize>() > std::mem::size_of::<Size>() {
if $cap > Size::MAX as usize {
[][$cap]
}
}
};
}
struct SetLenOnDrop<'a> {
len: &'a mut Size,
local_len: Size,
}
impl<'a> SetLenOnDrop<'a> {
#[inline]
fn new(len: &'a mut Size) -> Self {
SetLenOnDrop {
local_len: *len,
len,
}
}
#[inline(always)]
fn increment_len(&mut self, increment: Size) {
self.local_len += increment;
}
}
impl<'a> Drop for SetLenOnDrop<'a> {
#[inline]
fn drop(&mut self) {
*self.len = self.local_len;
}
}
pub struct Drain<'a, T: 'a, const N: usize> {
tail_start: usize,
tail_len: usize,
iter: slice::Iter<'a, T>,
vec: NonNull<StackVec<T, N>>,
}
unsafe impl<'a, T: Sync, const N: usize> Sync for Drain<'a, T, N> {}
unsafe impl<'a, T: Send, const N: usize> Send for Drain<'a, T, N> {}
impl<'a, T: 'a, const N: usize> Iterator for Drain<'a, T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|elt| unsafe { ptr::read(elt as *const _) })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, T: 'a, const N: usize> DoubleEndedIterator for Drain<'a, T, N> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|elt| unsafe { ptr::read(elt as *const _) })
}
}
impl<'a, T: 'a, const N: usize> ExactSizeIterator for Drain<'a, T, N> {}
impl<'a, T: 'a, const N: usize> Drop for Drain<'a, T, N> {
fn drop(&mut self) {
while let Some(_) = self.next() {}
if self.tail_len > 0 {
unsafe {
let source_vec = self.vec.as_mut();
let start = source_vec.len();
let tail = self.tail_start;
let src = source_vec.as_ptr().add(tail);
let dst = source_vec.as_mut_ptr().add(start);
ptr::copy(src, dst, self.tail_len);
source_vec.set_len(start + self.tail_len);
}
}
}
}
pub struct StackVec<T, const N: usize> {
vec: [MaybeUninit<T>; N],
len: Size,
}
impl<T, const N: usize> StackVec<T, N> {
const VALUE: MaybeUninit<T> = MaybeUninit::uninit();
const VEC: [MaybeUninit<T>; N] = [Self::VALUE; N];
#[inline]
pub const fn new() -> Self {
assert_capacity!(N);
StackVec {
vec: Self::VEC,
len: 0,
}
}
#[inline(always)]
pub const fn len(&self) -> usize {
self.len as usize
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub const fn is_full(&self) -> bool {
self.len() == self.capacity()
}
#[inline(always)]
pub const fn capacity(&self) -> usize {
N
}
#[inline]
pub const fn remaining_capacity(&self) -> usize {
self.capacity() - self.len()
}
#[inline(always)]
pub const fn as_ptr(&self) -> *const T {
self.vec.as_ptr() as _
}
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.vec.as_mut_ptr() as _
}
#[inline]
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
}
#[inline]
pub unsafe fn set_len(&mut self, length: usize) {
debug_assert!(length <= self.capacity());
self.len = length as Size;
}
#[inline]
pub fn push(&mut self, value: T) {
self.vec[self.len()] = MaybeUninit::new(value);
self.len += 1;
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
unsafe {
self.len -= 1;
Some(ptr::read(self.as_ptr().add(self.len())))
}
}
#[inline]
pub fn truncate(&mut self, len: usize) {
if len > self.len() {
return;
}
unsafe {
let remaining_len = self.len() - len;
let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len);
self.set_len(len);
ptr::drop_in_place(s);
}
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0)
}
#[inline]
pub fn insert(&mut self, index: usize, element: T) {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!(
"insertion index (is {}) should be <= len (is {})",
index, len
);
}
let len = self.len();
if index > len {
assert_failed(index, len);
}
assert!(len < self.capacity());
unsafe {
let ptr = self.as_mut_ptr().add(index);
ptr::copy(ptr, ptr.offset(1), len - index);
ptr::write(ptr, element);
self.set_len(len + 1);
}
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("removal index (is {}) should be < len (is {})", index, len);
}
let len = self.len();
if index >= len {
assert_failed(index, len);
}
unsafe {
let ret;
{
let ptr = self.as_mut_ptr().add(index);
ret = ptr::read(ptr);
ptr::copy(ptr.offset(1), ptr, len - index - 1);
}
self.set_len(len - 1);
ret
}
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!(
"swap_remove index (is {}) should be < len (is {})",
index, len
);
}
let len = self.len();
if index >= len {
assert_failed(index, len);
}
unsafe {
let last = ptr::read(self.as_ptr().add(len - 1));
let hole = self.as_mut_ptr().add(index);
self.set_len(len - 1);
ptr::replace(hole, last)
}
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> Drain<T, N>
where
R: RangeBounds<usize>,
{
let len = self.len();
let start = match range.start_bound() {
Bound::Unbounded => 0,
Bound::Included(&i) => i,
Bound::Excluded(&i) => i.saturating_add(1),
};
let end = match range.end_bound() {
Bound::Excluded(&j) => j,
Bound::Included(&j) => j.saturating_add(1),
Bound::Unbounded => len,
};
let range_slice: *const _ = &self[start..end];
self.len = start as Size;
unsafe {
Drain {
tail_start: end,
tail_len: len - end,
iter: (*range_slice).iter(),
vec: NonNull::new_unchecked(self as *mut _),
}
}
}
#[inline]
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let mut del = 0;
let len = self.len();
for i in 0..len {
if !f(&mut self[i]) {
del += 1;
} else if del > 0 {
self.swap(i - del, i);
}
}
self.truncate(len - del);
}
pub fn dedup_by<F>(&mut self, mut same_bucket: F)
where
F: FnMut(&mut T, &mut T) -> bool,
{
let len = self.len();
if len <= 1 {
return;
}
let ptr = self.as_mut_ptr();
let mut w: usize = 1;
unsafe {
for r in 1..len {
let p_r = ptr.add(r);
let p_wm1 = ptr.add(w - 1);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.add(1);
std::mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
}
}
self.truncate(w);
}
#[inline]
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
where
F: FnMut(&mut T) -> K,
K: PartialEq,
{
self.dedup_by(|a, b| key(a) == key(b))
}
}
impl<T: Clone, const N: usize> StackVec<T, N> {
#[inline]
pub fn from_elem(elem: T, n: usize) -> Self {
let mut vec = StackVec::<T, N>::new();
vec.push_elem(elem, n);
vec
}
#[inline]
pub fn push_elem(&mut self, elem: T, n: usize) {
assert!(self.remaining_capacity() >= n);
unsafe {
let ptr = self.as_mut_ptr();
let mut local_len = SetLenOnDrop::new(&mut self.len);
for _ in 0..n {
ptr::write(ptr.offset(local_len.local_len as isize), elem.clone());
local_len.increment_len(1);
}
}
}
#[inline]
pub fn extend_from_slice(&mut self, other: &[T]) {
assert!(self.remaining_capacity() >= other.len());
unsafe {
let ptr = self.as_mut_ptr();
let mut local_len = SetLenOnDrop::new(&mut self.len);
for elem in other {
ptr::write(ptr.offset(local_len.local_len as isize), elem.clone());
local_len.increment_len(1);
}
}
}
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
assert!(new_len <= self.capacity());
let len = self.len();
if new_len > len {
self.push_elem(value, new_len - len);
} else {
self.truncate(new_len);
}
}
}
impl<T: Copy, const N: usize> StackVec<T, N> {
#[inline]
pub fn copy_from_slice(&mut self, src: &[T]) {
assert!(self.remaining_capacity() >= src.len());
unsafe {
let dest = self.as_mut_ptr().add(self.len());
ptr::copy_nonoverlapping(src.as_ptr(), dest, src.len());
self.set_len(self.len() + src.len());
}
}
}
impl<T, const N: usize> Drop for StackVec<T, N> {
#[inline]
fn drop(&mut self) {
unsafe { ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len())) }
}
}
impl<T, const N: usize> From<[T; N]> for StackVec<T, N> {
#[inline]
fn from(array: [T; N]) -> Self {
let array = ManuallyDrop::new(array);
let mut vec = StackVec::<T, N>::new();
unsafe {
(&*array as *const [T; N] as *const [MaybeUninit<T>; N])
.copy_to_nonoverlapping(&mut vec.vec as *mut [MaybeUninit<T>; N], 1);
vec.set_len(N);
}
vec
}
}
impl<T, const N: usize> Clone for StackVec<T, N>
where
T: Clone,
{
#[inline]
fn clone(&self) -> Self {
self.iter().cloned().collect()
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.clear();
self.extend_from_slice(source);
}
}
impl<T, const N: usize> Deref for StackVec<T, N> {
type Target = [T];
#[inline(always)]
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> DerefMut for StackVec<T, N> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T, const N: usize> AsRef<[T]> for StackVec<T, N> {
#[inline(always)]
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> AsMut<[T]> for StackVec<T, N> {
#[inline(always)]
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T, const N: usize> Borrow<[T]> for StackVec<T, N> {
#[inline(always)]
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> BorrowMut<[T]> for StackVec<T, N> {
#[inline(always)]
fn borrow_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T, const N: usize> Default for StackVec<T, N> {
#[inline(always)]
fn default() -> StackVec<T, N> {
StackVec::new()
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for StackVec<T, N> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T, const N: usize> Hash for StackVec<T, N>
where
T: Hash,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}
impl<T, const N1: usize, const N2: usize> PartialEq<StackVec<T, N2>> for StackVec<T, N1>
where
T: PartialEq,
{
#[inline]
fn eq(&self, other: &StackVec<T, N2>) -> bool {
**self == **other
}
}
impl<T, const N: usize> PartialEq<[T]> for StackVec<T, N>
where
T: PartialEq,
{
#[inline]
fn eq(&self, other: &[T]) -> bool {
**self == *other
}
}
impl<T, const N: usize> Eq for StackVec<T, N> where T: Eq {}
impl<T: PartialOrd, const N1: usize, const N2: usize> PartialOrd<StackVec<T, N2>>
for StackVec<T, N1>
{
#[inline]
fn partial_cmp(&self, other: &StackVec<T, N2>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<T: Ord, const N: usize> Ord for StackVec<T, N> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<const N: usize> std::io::Write for StackVec<u8, N> {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.copy_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl<const N: usize> fmt::Write for StackVec<u8, N> {
#[inline]
fn write_str(&mut self, s: &str) -> fmt::Result {
self.copy_from_slice(s.as_bytes());
Ok(())
}
}
impl<T, const N: usize> Index<usize> for StackVec<T, N> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.as_slice()[index]
}
}
impl<T, const N: usize> IndexMut<usize> for StackVec<T, N> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.as_mut_slice()[index]
}
}
impl<T, const N: usize> Index<RangeFull> for StackVec<T, N> {
type Output = [T];
#[inline]
fn index(&self, _index: RangeFull) -> &Self::Output {
self.as_slice()
}
}
impl<T, const N: usize> IndexMut<RangeFull> for StackVec<T, N> {
#[inline]
fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output {
self.as_mut_slice()
}
}
macro_rules! impl_range_index {
($idx_ty: ty) => {
impl<T, const N: usize> Index<$idx_ty> for StackVec<T, N> {
type Output = [T];
#[inline]
fn index(&self, index: $idx_ty) -> &Self::Output {
&self.as_slice()[index]
}
}
impl<T, const N: usize> IndexMut<$idx_ty> for StackVec<T, N> {
#[inline]
fn index_mut(&mut self, index: $idx_ty) -> &mut Self::Output {
&mut self.as_mut_slice()[index]
}
}
};
($($idx_ty: ty),+ $(,)?) => {
$(impl_range_index!($idx_ty);)+
}
}
impl_range_index!(
Range<usize>,
RangeFrom<usize>,
RangeInclusive<usize>,
RangeTo<usize>,
RangeToInclusive<usize>,
);
impl<T, const N: usize> Extend<T> for StackVec<T, N> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for elem in iter.into_iter() {
self.push(elem);
}
}
}
impl<T, const N: usize> FromIterator<T> for StackVec<T, N> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut vec = StackVec::new();
vec.extend(iter);
vec
}
}
impl<'a, T, const N: usize> IntoIterator for &'a StackVec<T, N> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a mut StackVec<T, N> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T, const N: usize> IntoIterator for StackVec<T, N> {
type Item = T;
type IntoIter = IntoIter<T, N>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
vec: self,
index: 0,
}
}
}
pub struct IntoIter<T, const N: usize> {
vec: StackVec<T, N>,
index: usize,
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.vec.len() {
None
} else {
unsafe {
let index = self.index;
self.index = index + 1;
Some(ptr::read(self.vec.as_mut_ptr().add(index)))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.vec.len() - self.index;
(len, Some(len))
}
}
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.index == self.vec.len() {
None
} else {
unsafe {
let new_len = self.vec.len() - 1;
self.vec.set_len(new_len);
Some(ptr::read(self.vec.as_mut_ptr().add(new_len)))
}
}
}
}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
impl<T, const N: usize> Drop for IntoIter<T, N> {
#[inline]
fn drop(&mut self) {
let index = self.index;
let len = self.vec.len();
unsafe {
self.vec.set_len(0);
let elements = slice::from_raw_parts_mut(self.vec.as_mut_ptr().add(index), len - index);
ptr::drop_in_place(elements);
}
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(&self.vec[self.index..]).finish()
}
}
#[cfg(feature = "serde")]
mod impl_serde {
use super::*;
use serde::de::{Error, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::marker::PhantomData;
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<T: Serialize, const N: usize> Serialize for StackVec<T, N> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(self.as_slice())
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for StackVec<T, N> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct StackVecVisitor<'de, T: Deserialize<'de>, const N: usize>(
PhantomData<(&'de (), [T; N])>,
);
impl<'de, T: Deserialize<'de>, const N: usize> Visitor<'de> for StackVecVisitor<'de, T, N> {
type Value = StackVec<T, N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array with no more than {} items", N)
}
#[inline]
fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
where
SA: SeqAccess<'de>,
{
let mut values = StackVec::<T, N>::new();
while let Some(value) = seq.next_element()? {
if values.is_full() {
return Err(SA::Error::invalid_length(N + 1, &self));
}
values.push(value);
}
Ok(values)
}
}
deserializer.deserialize_seq(StackVecVisitor::<T, N>(PhantomData))
}
}
}
#[macro_export]
macro_rules! stack_vec {
() => ($crate::StackVec::new());
($ty: ty; $cap: literal) => ($crate::StackVec::<$ty, $cap>::new());
($elem:expr; $n:expr) => ({
$crate::StackVec::<_, $n>::from_elem($elem, $n)
});
($cap:literal# $elem:expr; $n:expr) => ({
$crate::StackVec::<_, $cap>::from_elem($elem, $n)
});
($($x:expr),+ $(,)?) => ({
$crate::StackVec::from([$($x),+])
});
($cap:literal# $($x:expr),+ $(,)?) => ({
let mut vec = $crate::StackVec::<_, $cap>::new();
$(vec.push($x);)+
vec
});
}