use core::fmt;
use core::mem::MaybeUninit;
use core::ops::{Deref, DerefMut};
pub struct ConstVec<T, const N: usize> {
data: [MaybeUninit<T>; N],
len: usize,
}
unsafe impl<T: Send, const N: usize> Send for ConstVec<T, N> {}
unsafe impl<T: Send, const N: usize> Sync for ConstVec<T, N> {}
impl<T, const N: usize> ConstVec<T, N> {
#[inline(always)]
pub fn new() -> Self {
let data = core::array::from_fn(|_| MaybeUninit::uninit());
Self { data, len: 0 }
}
#[inline(always)]
pub const fn len(&self) -> usize {
self.len
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline(always)]
pub const fn capacity(&self) -> usize {
N
}
#[inline(always)]
pub const fn is_full(&self) -> bool {
self.len == N
}
#[inline]
pub fn push(&mut self, item: T) -> Result<(), T> {
if self.len < N {
self.data[self.len] = MaybeUninit::new(item);
self.len += 1;
Ok(())
} else {
Err(item)
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
if self.len > 0 {
self.len -= 1;
let item = unsafe { self.data[self.len].assume_init_read() };
Some(item)
} else {
None
}
}
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
Some(unsafe { self.data[index].assume_init_ref() })
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len {
Some(unsafe { self.data[index].assume_init_mut() })
} else {
None
}
}
#[inline]
pub fn insert(&mut self, index: usize, item: T) -> Option<T> {
if index > self.len {
return None;
}
if self.len < N {
for i in (index..self.len).rev() {
unsafe {
let src = self.data[i].as_ptr();
let dst = self.data[i + 1].as_mut_ptr();
core::ptr::copy_nonoverlapping(src, dst, 1);
}
}
self.data[index] = MaybeUninit::new(item);
self.len += 1;
None
} else {
let last_item = unsafe { self.data[N - 1].assume_init_read() };
for i in (index..N - 1).rev() {
unsafe {
let src = self.data[i].as_ptr();
let dst = self.data[i + 1].as_mut_ptr();
core::ptr::copy_nonoverlapping(src, dst, 1);
}
}
self.data[index] = MaybeUninit::new(item);
Some(last_item)
}
}
#[inline]
pub fn iter(&self) -> core::slice::Iter<'_, T> {
self.deref().iter()
}
#[inline]
pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> {
self.deref_mut().iter_mut()
}
}
impl<T, const N: usize> Deref for ConstVec<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
unsafe { core::slice::from_raw_parts::<T>(self.data.as_ptr() as *const T, self.len) }
}
}
impl<T, const N: usize> DerefMut for ConstVec<T, N> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { core::slice::from_raw_parts_mut::<T>(self.data.as_mut_ptr() as *mut T, self.len) }
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for ConstVec<T, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ConstVec")
.field("len", &self.len)
.field("capacity", &N)
.field("data", &&self.data[..self.len])
.finish()
}
}
impl<T: Clone, const N: usize> Clone for ConstVec<T, N> {
fn clone(&self) -> Self {
let mut new_vec = Self::new();
for i in 0..self.len {
let item = unsafe { self.data[i].assume_init_ref() };
match new_vec.push(item.clone()) {
Ok(()) => {}
Err(_) => panic!("ConstVec clone failed: capacity exceeded"),
}
}
new_vec
}
}
impl<T: PartialEq, const N: usize> PartialEq for ConstVec<T, N> {
fn eq(&self, other: &Self) -> bool {
if self.len != other.len {
return false;
}
for i in 0..self.len {
let a = unsafe { self.data[i].assume_init_ref() };
let b = unsafe { other.data[i].assume_init_ref() };
if a != b {
return false;
}
}
true
}
}
impl<T: Eq, const N: usize> Eq for ConstVec<T, N> {}
impl<T, const N: usize> Default for ConstVec<T, N> {
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> core::ops::Index<usize> for ConstVec<T, N> {
type Output = T;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
self.get(index).expect("index out of bounds")
}
}
impl<T, const N: usize> core::ops::IndexMut<usize> for ConstVec<T, N> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.get_mut(index).expect("index out of bounds")
}
}
impl<T, const N: usize> Drop for ConstVec<T, N> {
fn drop(&mut self) {
for i in 0..self.len {
unsafe {
self.data[i].assume_init_drop();
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let vec: ConstVec<i32, 5> = ConstVec::new();
assert!(vec.is_empty());
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 5);
assert!(!vec.is_full());
}
#[test]
fn test_push_pop() {
let mut vec: ConstVec<i32, 3> = ConstVec::new();
assert!(vec.push(1).is_ok());
assert!(vec.push(2).is_ok());
assert!(vec.push(3).is_ok());
assert!(vec.is_full());
assert_eq!(vec.len(), 3);
assert_eq!(vec.push(4), Err(4));
assert_eq!(vec.len(), 3);
assert_eq!(vec.pop(), Some(3));
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.pop(), Some(1));
assert_eq!(vec.pop(), None);
assert!(vec.is_empty());
assert!(vec.push(10).is_ok());
assert_eq!(vec.pop(), Some(10));
}
#[test]
fn test_get() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(10).expect("push failed");
vec.push(20).expect("push failed");
vec.push(30).expect("push failed");
assert_eq!(vec.get(0), Some(&10));
assert_eq!(vec.get(1), Some(&20));
assert_eq!(vec.get(2), Some(&30));
assert_eq!(vec.get(3), None);
assert_eq!(vec.get(100), None);
}
#[test]
fn test_get_mut() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(10).expect("push failed");
vec.push(20).expect("push failed");
if let Some(elem) = vec.get_mut(0) {
*elem = 100;
}
assert_eq!(vec.get(0), Some(&100));
assert_eq!(vec.get(1), Some(&20));
}
#[test]
fn test_is_full() {
let mut vec: ConstVec<i32, 2> = ConstVec::new();
assert!(!vec.is_full());
vec.push(1).expect("push failed");
assert!(!vec.is_full());
vec.push(2).expect("push failed");
assert!(vec.is_full());
vec.pop();
assert!(!vec.is_full());
}
#[test]
fn test_clone() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
let cloned = vec.clone();
assert_eq!(cloned.len(), 3);
assert_eq!(cloned.get(0), Some(&1));
assert_eq!(cloned.get(1), Some(&2));
assert_eq!(cloned.get(2), Some(&3));
}
#[test]
fn test_eq() {
let mut vec1: ConstVec<i32, 5> = ConstVec::new();
vec1.push(1).expect("push failed");
vec1.push(2).expect("push failed");
let mut vec2: ConstVec<i32, 5> = ConstVec::new();
vec2.push(1).expect("push failed");
vec2.push(2).expect("push failed");
let mut vec3: ConstVec<i32, 5> = ConstVec::new();
vec3.push(1).expect("push failed");
vec3.push(3).expect("push failed");
assert_eq!(vec1, vec2);
assert_ne!(vec1, vec3);
}
#[test]
fn test_debug() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
let debug_str = format!("{:?}", vec);
assert!(debug_str.contains("ConstVec"));
assert!(debug_str.contains("len"));
assert!(debug_str.contains("capacity"));
}
#[test]
fn test_default() {
let vec: ConstVec<i32, 5> = ConstVec::default();
assert!(vec.is_empty());
assert_eq!(vec.capacity(), 5);
}
#[test]
fn test_drop() {
use crate::test::{CounterI32, alive_count, reset_alive_count};
reset_alive_count();
{
let mut vec: ConstVec<CounterI32, 3> = ConstVec::new();
vec.push(CounterI32::new(1)).expect("push failed");
vec.push(CounterI32::new(2)).expect("push failed");
vec.push(CounterI32::new(3)).expect("push failed");
assert_eq!(alive_count(), 3);
}
assert_eq!(alive_count(), 0);
}
#[test]
fn test_insert_not_full() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
assert_eq!(vec.insert(1, 10), None);
assert_eq!(vec.len(), 4);
assert_eq!(vec.get(0), Some(&1));
assert_eq!(vec.get(1), Some(&10));
assert_eq!(vec.get(2), Some(&2));
assert_eq!(vec.get(3), Some(&3));
assert_eq!(vec.get(4), None);
assert_eq!(vec.insert(0, 20), None);
assert_eq!(vec.len(), 5);
assert_eq!(vec.get(0), Some(&20));
assert_eq!(vec.get(1), Some(&1));
assert_eq!(vec.get(2), Some(&10));
assert_eq!(vec.get(3), Some(&2));
assert_eq!(vec.get(4), Some(&3));
assert!(vec.is_full());
}
#[test]
fn test_insert_full() {
let mut vec: ConstVec<i32, 4> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
vec.push(4).expect("push failed");
assert!(vec.is_full());
let removed = vec.insert(1, 10);
assert_eq!(removed, Some(4));
assert_eq!(vec.len(), 4); assert_eq!(vec.get(0), Some(&1));
assert_eq!(vec.get(1), Some(&10));
assert_eq!(vec.get(2), Some(&2));
assert_eq!(vec.get(3), Some(&3));
let removed = vec.insert(0, 20);
assert_eq!(removed, Some(3));
assert_eq!(vec.len(), 4);
assert_eq!(vec.get(0), Some(&20));
assert_eq!(vec.get(1), Some(&1));
assert_eq!(vec.get(2), Some(&10));
assert_eq!(vec.get(3), Some(&2));
}
#[test]
fn test_insert_at_end() {
let mut vec: ConstVec<i32, 4> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
assert_eq!(vec.insert(2, 10), None);
assert_eq!(vec.len(), 3);
assert_eq!(vec.get(0), Some(&1));
assert_eq!(vec.get(1), Some(&2));
assert_eq!(vec.get(2), Some(&10));
}
#[test]
fn test_insert_invalid_index() {
let mut vec: ConstVec<i32, 4> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
assert_eq!(vec.insert(5, 10), None);
assert_eq!(vec.len(), 2); assert_eq!(vec.get(0), Some(&1));
assert_eq!(vec.get(1), Some(&2));
}
#[test]
fn test_insert_empty() {
let mut vec: ConstVec<i32, 4> = ConstVec::new();
assert_eq!(vec.insert(0, 10), None);
assert_eq!(vec.len(), 1);
assert_eq!(vec.get(0), Some(&10));
}
#[test]
fn test_iter() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
let mut iter = vec.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), None);
let mut iter2 = vec.iter();
assert_eq!(iter2.size_hint(), (3, Some(3)));
iter2.next();
assert_eq!(iter2.size_hint(), (2, Some(2)));
}
#[test]
fn test_iter_mut() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
for elem in vec.iter_mut() {
*elem *= 2;
}
assert_eq!(vec.get(0), Some(&2));
assert_eq!(vec.get(1), Some(&4));
assert_eq!(vec.get(2), Some(&6));
let mut iter = vec.iter_mut();
assert_eq!(iter.next(), Some(&mut 2));
assert_eq!(iter.next(), Some(&mut 4));
assert_eq!(iter.next(), Some(&mut 6));
assert_eq!(iter.next(), None);
}
#[test]
fn test_index() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(10).expect("push failed");
vec.push(20).expect("push failed");
vec.push(30).expect("push failed");
assert_eq!(vec[0], 10);
assert_eq!(vec[1], 20);
assert_eq!(vec[2], 30);
fn get_element(vec: &ConstVec<i32, 5>, index: usize) -> i32 {
vec[index]
}
assert_eq!(get_element(&vec, 1), 20);
}
#[test]
fn test_index_mut() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(10).expect("push failed");
vec.push(20).expect("push failed");
vec[0] = 100;
vec[1] = 200;
assert_eq!(vec[0], 100);
assert_eq!(vec[1], 200);
fn double_first(vec: &mut ConstVec<i32, 5>) {
vec[0] *= 2;
}
double_first(&mut vec);
assert_eq!(vec[0], 200);
}
#[test]
#[should_panic(expected = "index out of bounds")]
#[cfg_attr(miri, ignore)]
fn test_index_out_of_bounds() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(10).expect("push failed");
let _ = vec[5]; }
#[test]
#[should_panic(expected = "index out of bounds")]
#[cfg_attr(miri, ignore)]
fn test_index_mut_out_of_bounds() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(10).expect("push failed");
vec[5] = 20; }
#[test]
fn test_empty_iter() {
let vec: ConstVec<i32, 5> = ConstVec::new();
let mut iter = vec.iter();
assert_eq!(iter.next(), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
#[test]
fn test_iter_exact_size() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
let iter = vec.iter();
assert_eq!(iter.len(), 3);
let iter_mut = vec.iter_mut();
assert_eq!(iter_mut.len(), 3);
}
#[test]
fn test_rev_iter() {
let mut vec: ConstVec<i32, 5> = ConstVec::new();
vec.push(1).expect("push failed");
vec.push(2).expect("push failed");
vec.push(3).expect("push failed");
let collected: Vec<i32> = vec.iter().rev().copied().collect();
assert_eq!(collected, vec![3, 2, 1]);
for elem in vec.iter_mut().rev() {
*elem *= 10;
}
assert_eq!(vec.get(0), Some(&10));
assert_eq!(vec.get(1), Some(&20));
assert_eq!(vec.get(2), Some(&30));
}
}