qecs-core 0.0.13

Soon to be highly flexible Entity-Component-System framework, core lib.
Documentation
use primitives::{Component, Id, Valid};

use downcast::Downcast;

use std::any::Any;

// ++++++++++++++++++++ StoreBase ++++++++++++++++++++

pub trait StoreBase: Any + Send + Sync {
    type Id: Id;

    fn len(&self) -> usize;

    fn is_assigned<'id>(&self, id: Valid<'id, Self::Id>) -> bool;

    fn assign_cloned<'id>(
        &mut self, 
        dest: Valid<'id, Self::Id>, 
        src: Valid<'id, Self::Id>,
    ) -> bool;

    /// A variant of `.release(id)` which drops the returned component. 
    /// Returns `true` if sucessful.
    fn release_drop<'id>(&mut self, id: Valid<'id, Self::Id>) -> bool;

    fn clear(&mut self);
}

impl<ID: Id, T: StoreBase<Id = ID>> Downcast<T> for StoreBase<Id = ID> {
    impl_downcast_items!(T);
}

impl<ID: Id> StoreBase<Id = ID> {
    downcast_method_items!();
}

impl<S: StoreBase + ?Sized> StoreBase for Box<S> {
    type Id = S::Id;

    fn len(&self) -> usize { (**self).len() }

    fn is_assigned<'id>(&self, id: Valid<'id, Self::Id>) -> bool { (**self).is_assigned(id) }

    fn assign_cloned<'id>(
        &mut self, 
        dest: Valid<'id, Self::Id>, 
        src: Valid<'id, Self::Id>,
    ) -> bool {
        (**self).assign_cloned(dest, src)
    }

    fn release_drop<'id>(&mut self, id: Valid<'id, Self::Id>) -> bool { (**self).release_drop(id) }

    fn clear(&mut self){ (**self).clear() }
}

// ++++++++++++++++++++ ComponentStore ++++++++++++++++++++

/// Workaround for lack of HK-lifetimes.
pub trait _ComponentStore<'a>: StoreBase {
    type _Component: Component;

    type Components: Iterator<Item = &'a Self::_Component> + 'a;
    
    type ComponentsMut: Iterator<Item = &'a mut Self::_Component> + 'a;
}

pub trait ComponentStore: StoreBase
    where Self: for<'a> _ComponentStore<'a, _Component = <Self as ComponentStore>::Component>
{
    type Component: Component; 

    fn assign<'id, T>(&mut self, id: Valid<'id, Self::Id>, com: T) -> Option<Self::Component>
        where T: Into<Self::Component>;

    fn release<'id>(&mut self, id: Valid<'id, Self::Id>) -> Option<Self::Component>;

    /// Returns `None` if `id` is not assigned.
    fn get<'id>(&self, id: Valid<'id, Self::Id>) -> Option<&Self::Component>;

    /// Returns `None` if `id` is not assigned.
    fn get_mut<'id>(&mut self, id: Valid<'id, Self::Id>) -> Option<&mut Self::Component>;

    fn components<'a>(&'a self) -> <Self as _ComponentStore<'a>>::Components;

    fn components_mut<'a>(&'a mut self) -> <Self as _ComponentStore<'a>>::ComponentsMut;
}

/// Workaround for lack of HK-lifetimes.
pub trait _ComponentStoreIter<'a>: _ComponentStore<'a> {
    type Iter: Iterator<Item = (Valid<'a, Self::Id>, &'a Self::_Component)> + 'a;

    type IterMut: Iterator<Item = (Valid<'a, Self::Id>, &'a mut Self::_Component)> + 'a;
}

pub trait ComponentStoreIter: ComponentStore
    where Self: for<'a> _ComponentStoreIter<'a>
{
    fn iter<'a>(&'a self) -> <Self as _ComponentStoreIter<'a>>::Iter;

    fn iter_mut<'a>(&'a mut self) -> <Self as _ComponentStoreIter<'a>>::IterMut;
}




/* NOTE: old code
pub trait SecondaryIdStoreTypes<'a, C: Id>: StoreBase {
    /// Some store-types don't store the primary-id themselves; for these the first
    /// tuple element will always yield `None`.
    type Iter: Iterator<Item = (Option<Valid<'a, Self::Id>>, Self::Output)>;

    /// Some store-types don't store the primary-id themselves; for these the first
    /// tuple element will always yield `None`.
    type IterMut: Iterator<Item = (Option<Valid<'a, Self::Id>>, &'a mut C)> = IterMutDummy<(Option<Valid<'a, Self::Id>>, &'a mut C)>;
}

pub trait SecondaryIdStore<C>: ComponentStore<C>
    where C: Id, Self: for<'a> ComponentStoreComponents<'a, C, Output = C>
{
    fn validate(&self, m_id: C) -> Option<Valid<Self::Id>>;

    fn invalidate(&mut self, id: C) -> Option<Valid<Self::Id>>;

    /// Generates a new id and activates it for `p_id`.
    fn generate_for<'id>(
        &mut self, 
        p_id: Valid<'id, Self::Id>
    ) -> IdGenerationResult<C>;

    fn activate_for<'id>(
        &mut self, 
        p_id: Valid<'id, Self::Id>,
        m_id: C,
    ) -> IdActivationResult<(), (C, Self::Id)>;

    /// TODO should this return `(C, Valid<Self::Id>)`?
    ///
    /// TODO should `id` be `usize`?
    fn slot_of(&mut self, m_id: C) -> Option<(C, Self::Id)>;
}
*/