#![allow(dead_code)]
use std::ptr::NonNull;
use std::marker::PhantomData;
use std::alloc::{self, Layout};
use std::ptr;
use array_init::array_init;
pub struct PackedArray<T, const N : usize> {
size : usize,
index_to_entry : [usize; N],
entry_to_index : [usize; N],
ptr : NonNull<T>,
_marker : PhantomData<T>
}
impl<T, const N : usize> PackedArray<T, N> {
pub fn new() -> Self {
let layout = Layout::array::<T>(N).unwrap();
let ptr = match NonNull::new(unsafe { alloc::alloc(layout) } as *mut T) {
Some(p) => p,
None => alloc::handle_alloc_error( layout ),
};
PackedArray {
size : 0,
index_to_entry : array_init(|i| i),
entry_to_index : array_init(|i| i),
ptr,
_marker : PhantomData
}
}
pub fn len(&self) -> usize {
self.size
}
pub fn has(&self, index : usize) -> bool {
self.index_to_entry[index] < self.size
}
pub fn full(&self) -> bool {
self.size == N
}
pub fn get(&self, index : usize) -> & T {
assert!(self.has(index));
unsafe {
&*self.get_ptr(self.index_to_entry[index])
}
}
pub fn get_mut(&mut self, index : usize) -> &mut T {
assert!(self.has(index));
unsafe {
&mut *self.get_ptr(self.index_to_entry[index])
}
}
pub fn append(&mut self, value : T) -> usize {
assert!(!self.full());
unsafe {
ptr::write(self.ptr.as_ptr().add(self.size), value);
}
self.size += 1;
self.entry_to_index[self.size-1]
}
pub fn set(&mut self, index : usize, value : T) {
if !self.has(index) {
self.swap_with_back(index);
self.size += 1;
}
self[index] = value;
}
pub fn remove(&mut self, index : usize) {
assert!(self.has(index));
self.size -= 1;
if self.index_to_entry[index] != self.size {
let entry_to_delete = self.index_to_entry[index];
unsafe {
ptr::copy_nonoverlapping(self.get_ptr(self.size), self.get_ptr(entry_to_delete), 1);
}
self.swap_with_back(index);
}
}
pub fn as_slice(&self) -> &[T] {
unsafe {
std::slice::from_raw_parts(self.ptr.as_ptr(), self.size)
}
}
pub fn as_slice_mut(&mut self) -> &mut [T] {
unsafe {
std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.size)
}
}
pub fn iter(&self) -> std::slice::Iter<'_, T> {
self.as_slice().iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
self.as_slice_mut().iter_mut()
}
fn swap_with_back(&mut self, index : usize) {
let entry = self.index_to_entry[index];
let last_index = self.entry_to_index[self.size];
self.index_to_entry.swap(index, last_index);
self.entry_to_index.swap(entry, self.size);
}
fn get_ptr(&self, entry : usize) -> *mut T {
unsafe {
self.ptr.as_ptr().add(entry)
}
}
}
impl<T, const N : usize> std::ops::Index<usize> for PackedArray<T, N> {
type Output = T;
fn index(&self, index : usize) -> &Self::Output {
self.get(index)
}
}
impl<T, const N : usize> std::ops::IndexMut<usize> for PackedArray<T, N> {
fn index_mut(&mut self, index : usize) -> &mut Self::Output {
self.get_mut(index)
}
}