#![no_std]
use bitmaps::{Bitmap, Bits, BitsImpl, Iter};
use core::mem::MaybeUninit;
pub struct FlattenObjects<T, const CAP: usize>
where
BitsImpl<{ CAP }>: Bits,
{
objects: [MaybeUninit<T>; CAP],
id_bitmap: Bitmap<CAP>,
count: usize,
}
impl<T, const CAP: usize> FlattenObjects<T, CAP>
where
BitsImpl<{ CAP }>: Bits,
{
pub const fn new() -> Self {
Self {
objects: [const { MaybeUninit::uninit() }; CAP],
id_bitmap: unsafe { MaybeUninit::zeroed().assume_init() },
count: 0,
}
}
#[inline]
pub const fn capacity(&self) -> usize {
CAP
}
#[inline]
pub const fn count(&self) -> usize {
self.count
}
#[inline]
pub fn is_assigned(&self, id: usize) -> bool {
id < CAP && self.id_bitmap.get(id)
}
#[inline]
pub fn get(&self, id: usize) -> Option<&T> {
if self.is_assigned(id) {
unsafe { Some(self.objects[id].assume_init_ref()) }
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self, id: usize) -> Option<&mut T> {
if self.is_assigned(id) {
unsafe { Some(self.objects[id].assume_init_mut()) }
} else {
None
}
}
pub fn add(&mut self, value: T) -> Result<usize, T> {
match self.id_bitmap.first_false_index() {
Some(id) if id < CAP => {
self.count += 1;
self.id_bitmap.set(id, true);
self.objects[id].write(value);
Ok(id)
}
_ => Err(value),
}
}
pub fn add_at(&mut self, id: usize, value: T) -> Result<usize, T> {
if id >= CAP || self.is_assigned(id) {
return Err(value);
}
self.count += 1;
self.id_bitmap.set(id, true);
self.objects[id].write(value);
Ok(id)
}
pub fn add_or_replace_at(&mut self, id: usize, value: T) -> Result<usize, Option<T>> {
if id >= CAP {
return Err(None);
}
if self.is_assigned(id) {
let old = unsafe { Some(self.objects[id].assume_init_read()) };
self.objects[id].write(value);
Err(old)
} else {
self.count += 1;
self.id_bitmap.set(id, true);
self.objects[id].write(value);
Ok(id)
}
}
pub fn remove(&mut self, id: usize) -> Option<T> {
if self.is_assigned(id) {
self.id_bitmap.set(id, false);
self.count -= 1;
unsafe { Some(self.objects[id].assume_init_read()) }
} else {
None
}
}
#[inline]
pub fn ids(&self) -> Iter<'_, CAP> {
self.id_bitmap.into_iter()
}
}
impl<T, const CAP: usize> Default for FlattenObjects<T, CAP>
where
BitsImpl<{ CAP }>: Bits,
{
fn default() -> Self {
Self::new()
}
}
impl<T: Clone, const CAP: usize> Clone for FlattenObjects<T, CAP>
where
BitsImpl<{ CAP }>: Bits,
{
fn clone(&self) -> Self {
let mut cloned = Self::new();
cloned.count = self.count;
cloned.id_bitmap = self.id_bitmap;
for id in &self.id_bitmap {
cloned.objects[id].write(unsafe { self.objects[id].assume_init_ref() }.clone());
}
cloned
}
}
impl<T, const CAP: usize> Drop for FlattenObjects<T, CAP>
where
BitsImpl<{ CAP }>: Bits,
{
fn drop(&mut self) {
for id in &self.id_bitmap {
unsafe { self.objects[id].assume_init_drop() };
}
}
}