qmi 0.1.5

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