use serde::{Serialize, ser::SerializeTuple};
use crate::EntityID;
#[derive(Debug, Clone, Copy)]
struct Page(pub [Option<usize>; 128]);
impl serde::Serialize for Page {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut tup = serializer.serialize_tuple(128)?;
for item in &self.0 {
tup.serialize_element(item)?;
}
tup.end()
}
}
#[derive(Serialize, Debug)]
pub struct PageMap {
pages: Vec<Option<Box<Page>>>,
}
impl PageMap {
pub fn new() -> Self {
Self { pages: Vec::new() }
}
#[inline]
pub fn insert(&mut self, entity_id: usize, dense_id: usize) {
let page_id = entity_id / 128;
let local_id = entity_id % 128;
if page_id >= self.pages.len() {
self.pages.resize(page_id + 1, None);
}
if self.pages[page_id].is_none() {
self.pages[page_id] = Some(Box::new(Page([None; 128])));
}
self.pages[page_id].as_mut().unwrap().0[local_id] = Some(dense_id);
}
#[inline]
pub fn get(&self, entity_id: usize) -> Option<usize> {
let page_id = entity_id / 128;
let local_id = entity_id % 128;
self.pages
.get(page_id)
.and_then(|page_opt| page_opt.as_ref())
.and_then(|page| page.0[local_id])
}
}
pub trait ComponentStorage {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
fn serialize(&self) -> Result<Vec<u8>, postcard::Error>;
fn type_name(&self) -> &'static str;
}
pub struct ComponentPool<T> {
pub dense_data: Vec<T>,
pub dense_entities: Vec<EntityID>,
pub sparse_map: PageMap,
}
impl<T: 'static + serde::Serialize> ComponentStorage for ComponentPool<T> {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn serialize(&self) -> Result<Vec<u8>, postcard::Error> {
postcard::to_allocvec(&(&self.sparse_map, &self.dense_entities, &self.dense_data))
}
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
impl<T> ComponentPool<T> {
pub fn iter_entities(&self) -> impl Iterator<Item = (EntityID, &T)> {
self.dense_entities
.iter()
.copied()
.zip(self.dense_data.iter())
}
pub fn iter_entities_mut(&mut self) -> impl Iterator<Item = (EntityID, &mut T)> {
self.dense_entities
.iter()
.copied()
.zip(self.dense_data.iter_mut())
}
}