qmi 0.1.4

An ECS with too much macro usage
Documentation
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())
    }
}