use core::mem::MaybeUninit;
use core::ops::{Deref, DerefMut};
#[derive(Debug)]
pub struct FixedVec<T, const N: usize> {
len: usize,
buf: [MaybeUninit<T>; N],
}
impl<T, const N: usize> FixedVec<T, N> {
pub const CAPACITY: usize = N;
pub const fn new() -> Self {
Self {
len: 0,
buf: [const { MaybeUninit::uninit() }; N],
}
}
pub fn from_value(value: T, len: usize) -> Self
where
T: Clone,
{
assert!(len <= N, "FixedVec capacity exceeded");
let mut s = Self::new();
for i in 0..len {
s.buf[i].write(value.clone());
}
s.len = len;
s
}
pub fn from_slice(src: &[T]) -> Self
where
T: Clone,
{
assert!(src.len() <= N, "FixedVec capacity exceeded");
let mut s = Self::new();
for (i, v) in src.iter().cloned().enumerate() {
s.buf[i].write(v);
}
s.len = src.len();
s
}
pub const fn len(&self) -> usize {
self.len
}
pub const fn is_empty(&self) -> bool {
self.len == 0
}
pub const fn capacity(&self) -> usize {
N
}
pub fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.buf.as_ptr() as *const T, self.len) }
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { core::slice::from_raw_parts_mut(self.buf.as_mut_ptr() as *mut T, self.len) }
}
pub fn as_storage_ptr(&self) -> *const T {
self.buf.as_ptr() as *const T
}
pub fn as_storage_mut_ptr(&mut self) -> *mut T {
self.buf.as_mut_ptr() as *mut T
}
pub fn push(&mut self, value: T) {
debug_assert!(self.len < N, "FixedVec push past capacity");
self.buf[self.len].write(value);
self.len += 1;
}
pub fn resize(&mut self, new_len: usize, value: T)
where
T: Clone,
{
assert!(new_len <= N, "FixedVec capacity exceeded");
if new_len > self.len {
for i in self.len..new_len {
self.buf[i].write(value.clone());
}
} else {
for i in new_len..self.len {
unsafe { self.buf[i].assume_init_drop() };
}
}
self.len = new_len;
}
pub fn truncate(&mut self, new_len: usize) {
if new_len < self.len {
for i in new_len..self.len {
unsafe { self.buf[i].assume_init_drop() };
}
self.len = new_len;
}
}
pub fn clear(&mut self) {
self.truncate(0);
}
pub unsafe fn set_len(&mut self, new_len: usize) {
assert!(new_len <= N, "FixedVec capacity exceeded");
self.len = new_len;
}
pub fn extend_from_slice(&mut self, src: &[T])
where
T: Clone,
{
let new_len = self.len + src.len();
assert!(new_len <= N, "FixedVec capacity exceeded");
for v in src {
self.buf[self.len].write(v.clone());
self.len += 1;
}
}
}
impl<T, const N: usize> Default for FixedVec<T, N> {
fn default() -> Self {
Self::new()
}
}
impl<T, const N: usize> Deref for FixedVec<T, N> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const N: usize> DerefMut for FixedVec<T, N> {
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl<T: Clone, const N: usize> Clone for FixedVec<T, N> {
fn clone(&self) -> Self {
let mut s = Self::new();
for i in 0..self.len {
let v = unsafe { self.buf[i].assume_init_ref() }.clone();
s.buf[i].write(v);
}
s.len = self.len;
s
}
}
impl<T, const N: usize> Drop for FixedVec<T, N> {
fn drop(&mut self) {
for i in 0..self.len {
unsafe { self.buf[i].assume_init_drop() };
}
}
}
unsafe impl<T: Sync, const N: usize> Sync for FixedVec<T, N> {}
unsafe impl<T: Send, const N: usize> Send for FixedVec<T, N> {}