use serde::{Deserialize, 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()
}
}
impl<'de> serde::Deserialize<'de> for Page {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct PageVisitor;
impl<'de> serde::de::Visitor<'de> for PageVisitor {
type Value = Page;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a tuple/sequence of exactly 128 Option<usize> elements")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut items = [None; 128];
for (i, slot) in items.iter_mut().enumerate() {
if let Some(element) = seq.next_element()? {
*slot = element;
} else {
return Err(serde::de::Error::invalid_length(i, &self));
}
}
Ok(Page(items))
}
}
deserializer.deserialize_tuple(128, PageVisitor)
}
}
#[derive(Serialize, Deserialize, 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 + for<'de> serde::Deserialize<'de>> 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: for<'de> serde::Deserialize<'de>> ComponentPool<T> {
pub fn deserialize(bytes: &[u8]) -> Result<Self, postcard::Error> {
let (sparse_map, dense_entities, dense_data): (PageMap, Vec<EntityID>, Vec<T>) =
postcard::from_bytes(bytes)?;
Ok(Self {
dense_data,
dense_entities,
sparse_map,
})
}
}
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())
}
}