ecs-lib-rs 0.1.1

An Entity Component System (ECS) Framework for learning.
Documentation
use std::any::{Any, TypeId};
use std::collections::HashMap;

#[derive(Default)]
pub struct Resources {
    data: HashMap<TypeId, Box<dyn Any>>,
}

impl Resources {
    pub fn add(&mut self, data: impl Any) {
        let type_id = data.type_id();
        self.data.insert(type_id, Box::new(data));
    }

    pub fn get_ref<T: Any>(&self) -> Option<&T> {
        let type_id = TypeId::of::<T>();
        if let Some(data) = self.data.get(&type_id) {
            return data.downcast_ref();
        }
        None
    }

    pub fn get_mut<T: Any>(&mut self) -> Option<&mut T> {
        let type_id = TypeId::of::<T>();
        if let Some(data) = self.data.get_mut(&type_id) {
            return data.downcast_mut();
        }
        None
    }

    pub fn remove<T: Any>(&mut self) -> Option<Box<dyn Any>> {
        self.data.remove(&TypeId::of::<T>())
    }
}

#[allow(clippy::float_cmp)]
#[cfg(test)]
mod tests {
    use crate::resources::Resources;
    use std::any::{Any, TypeId};

    #[derive(Debug, PartialEq)]
    struct WorldWidth(f32);

    #[test]
    fn add_resource() {
        let mut resources = Resources::default();
        let world_width = WorldWidth(100.0);
        resources.add(world_width);

        let stored_resource = resources.data.get(&TypeId::of::<WorldWidth>()).unwrap();
        let extracted_world_width = stored_resource.downcast_ref::<WorldWidth>().unwrap();

        assert_eq!(extracted_world_width.0, 100.0_f32);
    }

    #[test]
    fn get_resource() {
        let mut resources = Resources::default();
        let world_width = WorldWidth(100.0);
        assert_eq!(resources.get_ref::<WorldWidth>(), None);
        resources.add(world_width);
        assert_eq!(resources.get_ref::<WorldWidth>(), Some(&WorldWidth(100.0)));
    }

    #[test]
    fn get_mut() {
        let mut resources = Resources::default();
        let world_width = WorldWidth(100.0);
        assert_eq!(resources.get_mut::<WorldWidth>(), None);
        resources.add(world_width);
        {
            let world_width = resources.get_mut::<WorldWidth>();
            assert_eq!(world_width, Some(&mut WorldWidth(100.0)));
            let world_width = world_width.unwrap();
            (*world_width).0 += 100.0;
        }
        assert_eq!(resources.get_ref::<WorldWidth>(), Some(&WorldWidth(200.0)));
    }

    #[test]
    fn remove() {
        let mut resources = Resources::default();
        let world_width = WorldWidth(100.0);
        resources.add(world_width);
        assert_eq!(
            resources.remove::<WorldWidth>().map(|o| o.type_id()),
            Some((Box::new(WorldWidth(100.0)) as Box<dyn Any>).type_id())
        );
    }
}