matrix_engine 0.2.4

a small game engine developed by drmatrix
Documentation
use std::{
    any::{Any, TypeId},
    collections::{btree_map, BTreeMap, HashMap},
};

use super::{
    data_state::{DataState, DataStateAccessError, ReadDataState, WriteDataState},
    entity::Entity,
};

pub trait Component: Send + Sync + Any {}
impl<T: Send + Sync + Any> Component for T {}

#[derive(Debug)]
pub struct Components<C: Component> {
    data: BTreeMap<Entity, C>,
}
pub struct Iter<'a, C: Component> {
    data: btree_map::Iter<'a, Entity, C>,
}

impl<'a, C: Component> Iterator for Iter<'a, C> {
    type Item = (&'a Entity, &'a C);

    fn next(&mut self) -> Option<Self::Item> {
        self.data.next()
    }
}
impl<'a, C: Component> Iter<'a, C> {
    fn new(data: btree_map::Iter<'a, Entity, C>) -> Self {
        Self { data }
    }
}

pub struct IterMut<'a, C: Component> {
    data: btree_map::IterMut<'a, Entity, C>,
}

impl<'a, C: Component> Iterator for IterMut<'a, C> {
    type Item = (&'a Entity, &'a mut C);

    fn next(&mut self) -> Option<Self::Item> {
        self.data.next()
    }
}

impl<'a, C: Component> IterMut<'a, C> {
    fn new(data: btree_map::IterMut<'a, Entity, C>) -> Self {
        Self { data }
    }
}

impl<C: Component> Components<C> {
    pub fn new() -> Self {
        Self {
            data: BTreeMap::new(),
        }
    }

    pub fn iter(&self) -> Iter<'_, C> {
        Iter::<C>::new(self.data.iter())
    }
    pub fn iter_mut(&mut self) -> IterMut<'_, C> {
        IterMut::<C>::new(self.data.iter_mut())
    }
    pub fn insert(&mut self, e: Entity, c: C) {
        self.data.insert(e, c);
    }
    pub fn get(&self, e: &Entity) -> Option<&C> {
        self.data.get(e)
    }
    pub fn get_mut(&mut self, e: &Entity) -> Option<&mut C> {
        self.data.get_mut(e)
    }
}

impl<C: Component> Default for Components<C> {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Debug)]
pub struct ComponentRegistry {
    data: HashMap<TypeId, Box<dyn Any + Send>>,
}

impl ComponentRegistry {
    pub fn new() -> Self {
        Self {
            data: HashMap::new(),
        }
    }

    fn get_state<C: Component>(&mut self) -> &mut DataState<Components<C>> {
        self.data
            .entry(TypeId::of::<C>())
            .or_insert_with(|| Box::new(DataState::<Components<C>>::default()))
            .downcast_mut::<DataState<Components<C>>>()
            .expect("Failed to downcast data.")
    }

    pub fn read<C: Component>(
        &mut self,
    ) -> Result<ReadDataState<Components<C>>, DataStateAccessError> {
        self.get_state::<C>().read()
    }

    pub fn write<C: Component>(
        &mut self,
    ) -> Result<WriteDataState<Components<C>>, DataStateAccessError> {
        self.get_state::<C>().write()
    }

    pub fn consume_read<C: Component>(
        &mut self,
        read: ReadDataState<Components<C>>,
    ) -> Result<(), DataStateAccessError> {
        self.get_state::<C>().consume_read(read)
    }

    pub fn consume_write<C: Component>(
        &mut self,
        write: WriteDataState<Components<C>>,
    ) -> Result<(), DataStateAccessError> {
        self.get_state::<C>().consume_write(write)
    }

    pub fn check_read<C: Component>(&mut self) -> bool {
        self.get_state::<C>().can_read()
    }

    pub fn check_write<C: Component>(&mut self) -> bool {
        self.get_state::<C>().can_write()
    }

    pub fn try_insert<C: Component>(
        &mut self,
        e: Entity,
        c: C,
    ) -> Result<(), DataStateAccessError> {
        let w = self.get_state::<C>().get_mut()?;
        w.insert(e, c);
        Ok(())
    }
}

impl Default for ComponentRegistry {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use crate::engine::entity::Entity;

    use super::ComponentRegistry;

    #[test]
    pub fn simple_insert() {
        let mut reg = ComponentRegistry::new();
        let mut v = vec![];
        for i in 0..100 {
            let e = Entity::new();
            reg.try_insert::<i32>(e, i).unwrap();
            v.push((e, i));
        }

        let data = reg.read::<i32>().unwrap();

        for (e, i) in v {
            assert!(*data.get(&e).unwrap() == i);
        }
    }
    #[test]
    pub fn states() {
        let mut reg = ComponentRegistry::new();
        reg.try_insert(Entity::new(), ()).unwrap();

        let r = reg.read::<()>().unwrap();
        let b = reg.read::<()>().unwrap();

        let _ = reg.write::<()>().unwrap_err();

        reg.consume_read(r).unwrap();
        reg.consume_read(b).unwrap();

        let a = reg.write::<()>().unwrap();

        reg.read::<()>().unwrap_err();
        reg.write::<()>().unwrap_err();

        reg.consume_write(a).unwrap();
    }
}