use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::num::NonZeroUsize;
pub trait SparseStorage {
type EntityId : Copy;
fn get_index(&self, entity_id: Self::EntityId) -> Option<NonZeroUsize>;
fn set_index(&mut self, entity_id: Self::EntityId, index : Option<NonZeroUsize>);
fn clear(&mut self);
fn swap(&mut self,entity_id_1: Self::EntityId,entity_id_2: Self::EntityId) {
let index_1 = self.get_index(entity_id_1);
let index_2 = self.get_index(entity_id_2);
self.set_index(entity_id_1, index_2);
self.set_index(entity_id_2, index_1);
}
}
impl<E> SparseStorage for HashMap<E,NonZeroUsize>
where E : Hash + Eq + Copy{
type EntityId = E;
fn get_index(&self, entity_id: Self::EntityId) -> Option<NonZeroUsize> {
self.get(&entity_id).copied()
}
fn set_index(&mut self, entity_id: Self::EntityId, index : Option<NonZeroUsize>) {
if let Some(index) = index {
self.insert(entity_id, index);
} else {
self.remove(&entity_id);
}
}
fn clear(&mut self){
self.clear();
}
}
#[derive(Debug,Clone)]
pub struct VecWrapper<T,E>(Vec<T>,PhantomData<E>);
impl<T,E> Default for VecWrapper<T,E> {
fn default() -> Self {
Self(Default::default(), Default::default())
}
}
pub type VecStorage<E> = VecWrapper<Option<NonZeroUsize>,E>;
impl<E> SparseStorage for VecWrapper<Option<NonZeroUsize>,E>
where E : Into<usize> + Copy {
type EntityId = E;
fn get_index(&self, entity_id: Self::EntityId) -> Option<NonZeroUsize> {
let entity_id : usize = entity_id.into();
if entity_id < self.0.len() {
unsafe {
*self.0.get_unchecked(entity_id)
}
} else {
None
}
}
fn set_index(&mut self, entity_id: Self::EntityId, index : Option<NonZeroUsize>) {
let entity_id : usize = entity_id.into();
if entity_id > self.0.len() {
self.0.resize(entity_id + 1, None);
}
*unsafe { self.0.get_unchecked_mut(entity_id) } = index;
}
fn clear(&mut self) {
self.0.clear();
}
}