pkecs 9.0.0

Another ECS implementation.
Documentation
//! Contains the component store.

pub(crate) mod channel;

use std::{any::TypeId, collections::HashMap, hash::Hash};
use super::query::*;
use channel::{ComponentChannel, ComponentMap, ErasedComponentChannel};

/// A component/object store.
///
/// NOTES:
/// - Components cannot be deleted (yet).
/// - There is no concept on an entity, this is essentially an object store.
#[derive(Default)]
pub struct Components {
    /// A map of component channels indexed by the type they contain.
    components: HashMap<TypeId, Box<dyn ErasedComponentChannel>>,
}

impl Components {
    /// Adds a component to [`self`].
    pub fn spawn<C>(&mut self, component: C)
        where
            C: 'static,
    {
        let id = TypeId::of::<C>();

        self.components
            .entry(id)
            .or_insert(ComponentChannel::<C>::new_box())
            .as_any_mut()
            .downcast_mut::<ComponentChannel<C>>()
            .map(|c| c.push(component));
    }

    /// Adds an indexed component to [`self`].
    pub fn spawn_indexed<K, C>(&mut self, key: K, component: C)
        where
            K: Eq + Hash + 'static,
            C: 'static,
    {
        let id = TypeId::of::<(K, C)>();

        self.components
            .entry(id)
            .or_insert(ComponentMap::<K, C>::new_box())
            .as_any_mut()
            .downcast_mut::<ComponentMap<K, C>>()
            .map(|c| c.insert(key, component));
    }
    /// Retrieves an immutable reference to component set.
    pub fn query<'c, C>(&'c self) -> Query<'c, C>
        where
            C: 'static,
    {
        let id = TypeId::of::<C>();

        let channel = self.components
            .get(&id)
            .map(|c| c.as_any())
            .and_then(|c| c.downcast_ref::<ComponentChannel::<C>>());

        Query::<C>::from_channel(channel)
    }

    /// Retrieves a mutable referent to an component set.
    pub fn query_mut<'c, C>(&'c mut self) -> QueryMut<'c, C>
        where
            C: 'static,
    {
        let id = TypeId::of::<C>();

        let channel = self.components
            .get_mut(&id)
            .map(|c| c.as_any_mut())
            .and_then(|c| c.downcast_mut::<ComponentChannel::<C>>());

        QueryMut::<C>::from_channel(channel)
    }

    /// Retrieves an immutable reference to an indexed channel of components.
    pub fn query_indexed<'c, K, C>(&'c self) -> QueryIndexed<'c, K, C>
        where
            K: Eq + Hash + 'static,
            C: 'static,
    {
        let id = TypeId::of::<(K, C)>();

        let channel = self.components
            .get(&id)
            .map(|c| c.as_any())
            .and_then(|c| c.downcast_ref::<ComponentMap<K, C>>());

        QueryIndexed::from_channel(channel)
    }

    /// Retrieves a mutable reference to an indexed channel of components.
    pub fn query_indexed_mut<'c, K, C>(&'c mut self) -> QueryIndexedMut<'c, K, C>
        where
            K: Eq + Hash + 'static,
            C: 'static,
    {
        let id = TypeId::of::<(K, C)>();

        let channel = self.components
            .get_mut(&id)
            .map(|c| c.as_any_mut())
            .and_then(|c| c.downcast_mut::<ComponentMap<K, C>>());

        QueryIndexedMut::from_channel(channel)
    }
}