#![no_std]
#![allow(clippy::inline_always)]
#![allow(clippy::doc_markdown)]
#![allow(incomplete_features)]
#![feature(const_fn)]
#![feature(const_generics)]
#![feature(const_if_match)]
#![feature(const_raw_ptr_to_usize_cast)]
#![feature(core_intrinsics)]
#![feature(doc_cfg)]
#![feature(exact_size_is_empty)]
#![feature(maybe_uninit_extra)]
#![feature(maybe_uninit_ref)]
#![feature(maybe_uninit_uninit_array)]
#![cfg_attr(feature = "std", feature(read_initializer))]
#![feature(slice_from_raw_parts)]
#![feature(slice_partition_dedup)]
#![feature(specialization)]
#![feature(trusted_len)]
pub use crate::errors::{CapacityError, PushCapacityError};
pub use crate::iterators::*;
pub use crate::trait_impls::*;
use crate::utils::reverse_copy;
use core::cmp::{Ord, PartialEq};
use core::intrinsics;
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::ops::{
Add, Bound::Excluded, Bound::Included, Bound::Unbounded, Div, Mul, RangeBounds, Sub,
};
use core::ptr;
#[cfg(any(feature = "std", rustdoc))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
#[cfg(any(feature = "std", rustdoc))]
use alloc::vec::Vec;
mod iterators;
#[macro_use]
mod macros;
#[doc(hidden)]
mod errors;
mod trait_impls;
#[doc(hidden)]
pub mod utils;
#[cfg_attr(feature = "repr_c", repr(C))]
pub struct StaticVec<T, const N: usize> {
data: MaybeUninit<[T; N]>,
length: usize,
}
impl<T, const N: usize> StaticVec<T, N> {
#[inline(always)]
pub const fn new() -> Self {
Self {
data: Self::new_data_uninit(),
length: 0,
}
}
#[inline]
pub fn new_from_slice(values: &[T]) -> Self
where T: Copy {
let length = values.len().min(N);
Self {
data: {
let mut data = Self::new_data_uninit();
unsafe {
values
.as_ptr()
.copy_to_nonoverlapping(data.as_mut_ptr() as *mut T, length);
data
}
},
length,
}
}
#[inline]
pub fn new_from_array<const N2: usize>(values: [T; N2]) -> Self {
if N == N2 {
Self::from(values)
} else {
Self {
data: {
unsafe {
let mut data = Self::new_data_uninit();
values
.as_ptr()
.copy_to_nonoverlapping(data.as_mut_ptr() as *mut T, N2.min(N));
let mut forgotten = MaybeUninit::new(values);
ptr::drop_in_place(forgotten.get_mut().get_unchecked_mut(N2.min(N)..N2));
data
}
},
length: N2.min(N),
}
}
}
#[inline(always)]
pub const fn new_from_const_array(values: [T; N]) -> Self {
Self {
data: MaybeUninit::new(values),
length: N,
}
}
#[inline(always)]
pub const fn len(&self) -> usize {
self.length
}
#[inline(always)]
pub const fn capacity(&self) -> usize {
N
}
#[inline(always)]
pub const fn cap() -> usize {
N
}
pub const CAPACITY: usize = N;
#[inline(always)]
pub const fn remaining_capacity(&self) -> usize {
N - self.length
}
#[inline(always)]
pub const fn size_in_bytes(&self) -> usize {
intrinsics::size_of::<T>() * self.length
}
#[inline(always)]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(
new_len <= N,
"Attempted to unsafely set length to {}; maximum is {}!",
new_len,
N
);
self.length = new_len;
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.length == 0
}
#[inline(always)]
pub const fn is_not_empty(&self) -> bool {
self.length > 0
}
#[inline(always)]
pub const fn is_full(&self) -> bool {
self.length == N
}
#[inline(always)]
pub const fn is_not_full(&self) -> bool {
self.length < N
}
#[inline(always)]
pub const fn as_ptr(&self) -> *const T {
&self.data as *const _ as *const T
}
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr() as *mut T
}
#[inline(always)]
pub fn as_slice(&self) -> &[T] {
unsafe { &*ptr::slice_from_raw_parts(self.as_ptr(), self.length) }
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { &mut *ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.length) }
}
#[inline(always)]
pub unsafe fn ptr_at_unchecked(&self, index: usize) -> *const T {
self.as_ptr().add(index)
}
#[inline(always)]
pub unsafe fn mut_ptr_at_unchecked(&mut self, index: usize) -> *mut T {
self.as_mut_ptr().add(index)
}
#[inline(always)]
pub fn ptr_at(&self, index: usize) -> *const T {
assert!(
index < self.length,
"Provided index {} must be between 0 and {}!",
index,
self.length
);
unsafe { self.ptr_at_unchecked(index) }
}
#[inline(always)]
pub fn mut_ptr_at(&mut self, index: usize) -> *mut T {
assert!(
index < self.length,
"Provided index {} must be between 0 and {}!",
index,
self.length
);
unsafe { self.mut_ptr_at_unchecked(index) }
}
#[inline(always)]
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
debug_assert!(
index < self.length,
"Attempted to unsafely get at index {} when length is {}!",
index,
self.length
);
&*self.ptr_at_unchecked(index)
}
#[inline(always)]
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
debug_assert!(
index < self.length,
"Attempted to unsafely get at index {} when length is {}!",
index,
self.length
);
&mut *self.mut_ptr_at_unchecked(index)
}
#[inline(always)]
pub unsafe fn push_unchecked(&mut self, value: T) {
debug_assert!(
self.is_not_full(),
"Attempted to unsafely push to a full StaticVec!"
);
self.mut_ptr_at_unchecked(self.length).write(value);
self.length += 1;
}
#[inline(always)]
pub unsafe fn pop_unchecked(&mut self) -> T {
debug_assert!(
self.is_not_empty(),
"Attempted to unsafely pop from an empty StaticVec!"
);
self.length -= 1;
self.ptr_at_unchecked(self.length).read()
}
#[inline(always)]
pub fn try_push(&mut self, value: T) -> Result<(), PushCapacityError<T, N>> {
if self.length < N {
unsafe {
self.push_unchecked(value);
};
Ok(())
} else {
Err(PushCapacityError::new(value))
}
}
#[inline(always)]
pub fn push(&mut self, value: T) {
assert!(self.length < N);
unsafe { self.push_unchecked(value) };
}
#[inline(always)]
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
Some(unsafe { self.pop_unchecked() })
}
}
#[inline(always)]
pub fn first(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
Some(unsafe { self.get_unchecked(0) })
}
}
#[inline(always)]
pub fn first_mut(&mut self) -> Option<&mut T> {
if self.is_empty() {
None
} else {
Some(unsafe { self.get_unchecked_mut(0) })
}
}
#[inline(always)]
pub fn last(&self) -> Option<&T> {
if self.is_empty() {
None
} else {
Some(unsafe { self.get_unchecked(self.length - 1) })
}
}
#[inline(always)]
pub fn last_mut(&mut self) -> Option<&mut T> {
if self.is_empty() {
None
} else {
Some(unsafe { self.get_unchecked_mut(self.length - 1) })
}
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.length);
unsafe {
let p = self.mut_ptr_at_unchecked(index);
let res = p.read();
p.offset(1).copy_to(p, self.length - index - 1);
self.length -= 1;
res
}
}
#[inline(always)]
pub fn remove_item(&mut self, item: &T) -> Option<T>
where T: PartialEq {
if let Some(pos) = self.iter().position(|x| *x == *item) {
Some(self.remove(pos))
} else {
None
}
}
#[inline(always)]
pub fn swap_pop(&mut self, index: usize) -> Option<T> {
if index < self.length {
unsafe {
let last_value = self.ptr_at_unchecked(self.length - 1).read();
self.length -= 1;
Some(self.mut_ptr_at_unchecked(index).replace(last_value))
}
} else {
None
}
}
#[inline(always)]
pub fn swap_remove(&mut self, index: usize) -> T {
assert!(index < self.length);
unsafe {
let last_value = self.ptr_at_unchecked(self.length - 1).read();
self.length -= 1;
self.mut_ptr_at_unchecked(index).replace(last_value)
}
}
#[inline]
pub fn insert(&mut self, index: usize, value: T) {
assert!(self.length < N && index <= self.length);
unsafe {
let p = self.mut_ptr_at_unchecked(index);
p.copy_to(p.offset(1), self.length - index);
p.write(value);
self.length += 1;
}
}
#[inline]
pub fn insert_many<I: IntoIterator<Item = T>>(&mut self, index: usize, iter: I)
where I::IntoIter: ExactSizeIterator<Item = T> {
assert!(
self.length < N && index <= self.length,
"Insufficient remaining capacity / out of bounds!"
);
let mut it = iter.into_iter();
if index == self.length {
return self.extend(it);
}
let iter_size = it.len();
assert!(
index + iter_size >= index && (self.length - index) + iter_size < N,
"Insufficient remaining capacity / out of bounds!"
);
unsafe {
let old_length = self.length;
let mut this = self.mut_ptr_at_unchecked(index);
this.copy_to(this.add(iter_size), old_length - index);
self.length = index;
let mut item_count = 0;
while item_count < N {
if let Some(element) = it.next() {
let mut current = this.add(item_count);
if item_count >= iter_size {
this = self.mut_ptr_at_unchecked(index);
current = this.add(item_count);
current.copy_to(current.offset(1), old_length - index);
}
current.write(element);
item_count += 1;
} else {
break;
}
}
self.length = old_length + item_count;
}
}
#[inline]
pub fn try_insert(&mut self, index: usize, value: T) -> Result<(), CapacityError<N>> {
if self.length < N && index <= self.length {
unsafe {
let p = self.mut_ptr_at_unchecked(index);
p.copy_to(p.offset(1), self.length - index);
p.write(value);
self.length += 1;
Ok(())
}
} else {
Err(CapacityError {})
}
}
#[inline(always)]
pub fn contains(&self, value: &T) -> bool
where T: PartialEq {
self.iter().any(|current| current == value)
}
#[inline(always)]
pub fn clear(&mut self) {
unsafe {
ptr::drop_in_place(self.as_mut_slice());
}
self.length = 0;
}
#[inline(always)]
pub fn iter(&self) -> StaticVecIterConst<T, N> {
StaticVecIterConst {
start: self.as_ptr(),
end: match intrinsics::size_of::<T>() {
0 => (self.as_ptr() as *const u8).wrapping_add(self.length) as *const T,
_ => unsafe { self.ptr_at_unchecked(self.length) },
},
marker: PhantomData,
}
}
#[inline(always)]
pub fn iter_mut(&mut self) -> StaticVecIterMut<T, N> {
StaticVecIterMut {
start: self.as_mut_ptr(),
end: match intrinsics::size_of::<T>() {
0 => (self.as_mut_ptr() as *mut u8).wrapping_add(self.length) as *mut T,
_ => unsafe { self.mut_ptr_at_unchecked(self.length) },
},
marker: PhantomData,
}
}
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline]
pub fn sorted(&self) -> Self
where T: Copy + Ord {
let mut res = self.clone();
res.sort();
res
}
#[inline]
pub fn sorted_unstable(&self) -> Self
where T: Copy + Ord {
let mut res = self.clone();
res.sort_unstable();
res
}
#[inline(always)]
pub fn reversed(&self) -> Self
where T: Copy {
Self {
data: reverse_copy(&self.data),
length: self.length,
}
}
#[inline]
pub fn filled_with<F>(mut initializer: F) -> Self
where F: FnMut() -> T {
let mut res = Self::new();
for i in 0..N {
unsafe {
res.mut_ptr_at_unchecked(i).write(initializer());
res.length += 1;
}
}
res
}
#[inline]
pub fn filled_with_by_index<F>(mut initializer: F) -> Self
where F: FnMut(usize) -> T {
let mut res = Self::new();
for i in 0..N {
unsafe {
res.mut_ptr_at_unchecked(i).write(initializer(i));
res.length += 1;
}
}
res
}
#[inline(always)]
pub fn extend_from_slice(&mut self, other: &[T])
where T: Copy {
let added_length = other.len().min(self.remaining_capacity());
unsafe {
other
.as_ptr()
.copy_to_nonoverlapping(self.mut_ptr_at_unchecked(self.length), added_length);
}
self.length += added_length;
}
#[inline(always)]
pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError<N>>
where T: Copy {
let added_length = other.len();
if self.remaining_capacity() < added_length {
return Err(CapacityError {});
}
unsafe {
other
.as_ptr()
.copy_to_nonoverlapping(self.mut_ptr_at_unchecked(self.length), added_length);
}
self.length += added_length;
Ok(())
}
#[inline]
pub fn append<const N2: usize>(&mut self, other: &mut StaticVec<T, N2>) {
let item_count = self.remaining_capacity().min(other.length);
let other_new_length = other.length - item_count;
unsafe {
self
.mut_ptr_at_unchecked(self.length)
.copy_from_nonoverlapping(other.as_ptr(), item_count);
other
.as_mut_ptr()
.copy_from(other.ptr_at_unchecked(item_count), other_new_length);
}
other.length = other_new_length;
self.length += item_count;
}
#[inline]
pub fn concat<const N2: usize>(&self, other: &StaticVec<T, N2>) -> StaticVec<T, { N + N2 }>
where T: Copy {
let mut res = StaticVec::new();
unsafe {
self
.as_ptr()
.copy_to_nonoverlapping(res.as_mut_ptr(), self.length);
other
.as_ptr()
.copy_to_nonoverlapping(res.mut_ptr_at_unchecked(self.length), other.length);
}
res.length = self.length + other.length;
res
}
#[inline]
pub fn concat_clone<const N2: usize>(
&self,
other: &StaticVec<T, N2>,
) -> StaticVec<T, { N + N2 }>
where
T: Clone,
{
let mut res = StaticVec::new();
for i in 0..self.length {
unsafe { res.push_unchecked(self.get_unchecked(i).clone()) };
}
for i in 0..other.length {
unsafe { res.push_unchecked(other.get_unchecked(i).clone()) };
}
res
}
#[inline]
pub fn intersperse(&self, separator: T) -> StaticVec<T, { N * 2 }>
where T: Copy {
if self.is_empty() {
return StaticVec::new();
}
let mut res = StaticVec::new();
let mut res_ptr = res.as_mut_ptr() as *mut T;
let mut self_ptr = self.as_ptr();
for _ in 0..self.length - 1 {
unsafe {
res_ptr.write(self_ptr.read());
res_ptr = res_ptr.offset(1);
res_ptr.write(separator);
res_ptr = res_ptr.offset(1);
self_ptr = self_ptr.offset(1);
}
}
unsafe { res_ptr.write(self_ptr.read()) };
res.length = (self.length * 2) - 1;
res
}
#[inline]
pub fn intersperse_clone(&self, separator: T) -> StaticVec<T, { N * 2 }>
where T: Clone {
if self.is_empty() {
return StaticVec::new();
}
let mut res = StaticVec::new();
unsafe {
for item in self.as_slice().get_unchecked(0..self.length - 1) {
res.push_unchecked(item.clone());
res.push_unchecked(separator.clone());
}
res.push_unchecked(self.get_unchecked(self.length - 1).clone());
}
res
}
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline]
pub fn from_vec(mut vec: Vec<T>) -> Self {
let vec_len = vec.len();
let item_count = vec_len.min(N);
Self {
data: {
unsafe { vec.set_len(0) };
let mut data = Self::new_data_uninit();
unsafe {
vec
.as_ptr()
.copy_to_nonoverlapping(data.as_mut_ptr() as *mut T, item_count);
if vec_len > item_count {
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
vec.as_mut_ptr().add(item_count),
vec_len - item_count,
));
}
data
}
},
length: item_count,
}
}
#[cfg(feature = "std")]
#[doc(cfg(feature = "std"))]
#[inline(always)]
pub fn into_vec(mut self) -> Vec<T> {
let mut res = Vec::with_capacity(N);
unsafe {
self
.as_ptr()
.copy_to_nonoverlapping(res.as_mut_ptr(), self.length);
res.set_len(self.length);
self.length = 0;
res
}
}
#[inline]
pub fn drain<R>(&mut self, range: R) -> Self
where R: RangeBounds<usize> {
let start = match range.start_bound() {
Included(&idx) => idx,
Excluded(&idx) => idx + 1,
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&idx) => idx + 1,
Excluded(&idx) => idx,
Unbounded => self.length,
};
assert!(start <= end && end <= self.length);
let res_length = end - start;
Self {
data: {
let mut res = Self::new_data_uninit();
unsafe {
self
.ptr_at_unchecked(start)
.copy_to_nonoverlapping(res.as_mut_ptr() as *mut T, res_length);
self
.ptr_at_unchecked(end)
.copy_to(self.mut_ptr_at_unchecked(start), self.length - end);
self.length -= res_length;
res
}
},
length: res_length,
}
}
#[inline]
pub fn drain_filter<F>(&mut self, mut filter: F) -> Self
where F: FnMut(&mut T) -> bool {
let mut res = Self::new();
let old_length = self.length;
self.length = 0;
unsafe {
for i in 0..old_length {
let val = self.mut_ptr_at_unchecked(i);
if filter(&mut *val) {
res.mut_ptr_at_unchecked(res.length).write(val.read());
res.length += 1;
} else if res.length > 0 {
self
.ptr_at_unchecked(i)
.copy_to_nonoverlapping(self.mut_ptr_at_unchecked(i - res.length), 1);
}
}
}
self.length = old_length - res.length;
res
}
#[inline(always)]
pub fn retain<F>(&mut self, mut filter: F)
where F: FnMut(&T) -> bool {
self.drain_filter(|val| !filter(val));
}
#[inline(always)]
pub fn truncate(&mut self, length: usize) {
if length < self.length {
let old_length = self.length;
self.length = length;
unsafe {
ptr::drop_in_place(self.as_mut_slice().get_unchecked_mut(length..old_length));
}
}
}
#[inline]
pub fn split_off(&mut self, at: usize) -> Self {
assert!(at <= self.length);
let split_length = self.length - at;
self.length = at;
Self {
data: unsafe {
let mut split = Self::new_data_uninit();
self
.ptr_at_unchecked(at)
.copy_to_nonoverlapping(split.as_mut_ptr() as *mut T, split_length);
split
},
length: split_length,
}
}
#[inline(always)]
pub fn dedup_by<F>(&mut self, same_bucket: F)
where F: FnMut(&mut T, &mut T) -> bool {
let new_length = self.as_mut_slice().partition_dedup_by(same_bucket).0.len();
self.truncate(new_length);
}
#[inline(always)]
pub fn dedup(&mut self)
where T: PartialEq {
self.dedup_by(|a, b| a == b)
}
#[inline(always)]
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
where
F: FnMut(&mut T) -> K,
K: PartialEq<K>, {
self.dedup_by(|a, b| key(a) == key(b))
}
#[inline]
pub fn difference<const N2: usize>(&self, other: &StaticVec<T, N2>) -> Self
where T: Clone + PartialEq {
let mut res = Self::new();
for left in self {
let mut found = false;
for right in other {
if left == right {
found = true;
break;
}
}
if !found {
unsafe { res.push_unchecked(left.clone()) }
}
}
res
}
#[inline]
pub fn symmetric_difference<const N2: usize>(
&self,
other: &StaticVec<T, N2>,
) -> StaticVec<T, { N + N2 }>
where
T: Clone + PartialEq,
{
let mut res = StaticVec::new();
for left in self {
let mut found = false;
for right in other {
if left == right {
found = true;
break;
}
}
if !found {
unsafe { res.push_unchecked(left.clone()) }
}
}
for right in other {
let mut found = false;
for left in self {
if right == left {
found = true;
break;
}
}
if !found {
unsafe { res.push_unchecked(right.clone()) }
}
}
res
}
#[inline]
pub fn intersection<const N2: usize>(&self, other: &StaticVec<T, N2>) -> Self
where T: Clone + PartialEq {
let mut res = Self::new();
for left in self {
let mut found = false;
for right in other {
if left == right {
found = true;
break;
}
}
if found && !res.contains(left) {
unsafe { res.push_unchecked(left.clone()) }
}
}
res
}
#[inline(always)]
pub const fn triple(&self) -> (*const T, usize, usize) {
(self.as_ptr(), self.length, N)
}
#[inline(always)]
pub fn triple_mut(&mut self) -> (*mut T, usize, usize) {
(self.as_mut_ptr(), self.length, N)
}
#[inline(always)]
pub fn added(&self, other: &Self) -> Self
where T: Copy + Add<Output = T> {
assert!(self.is_full() && other.is_full());
let mut res = Self::new();
for i in 0..N {
unsafe {
res
.mut_ptr_at_unchecked(i)
.write(*self.get_unchecked(i) + *other.get_unchecked(i));
}
}
res.length = N;
res
}
#[inline(always)]
pub fn subtracted(&self, other: &Self) -> Self
where T: Copy + Sub<Output = T> {
assert!(self.is_full() && other.is_full());
let mut res = Self::new();
for i in 0..N {
unsafe {
res
.mut_ptr_at_unchecked(i)
.write(*self.get_unchecked(i) - *other.get_unchecked(i));
}
}
res.length = N;
res
}
#[inline(always)]
pub fn multiplied(&self, other: &Self) -> Self
where T: Copy + Mul<Output = T> {
assert!(self.is_full() && other.is_full());
let mut res = Self::new();
for i in 0..N {
unsafe {
res
.mut_ptr_at_unchecked(i)
.write(*self.get_unchecked(i) * *other.get_unchecked(i));
}
}
res.length = N;
res
}
#[inline(always)]
pub fn divided(&self, other: &Self) -> Self
where T: Copy + Div<Output = T> {
assert!(self.is_full() && other.is_full());
let mut res = Self::new();
for i in 0..N {
unsafe {
res
.mut_ptr_at_unchecked(i)
.write(*self.get_unchecked(i) / *other.get_unchecked(i));
}
}
res.length = N;
res
}
#[doc(hidden)]
#[inline(always)]
pub(crate) const fn new_data_uninit() -> MaybeUninit<[T; N]> {
MaybeUninit::uninit()
}
}