qecs-core 0.0.17

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

use downcast::Downcast;

use std::borrow::Borrow;

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

pub trait StoreBase: ServiceBase {
    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!();
}

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

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

    type Values: Iterator<Item = &'a Self::_Value> + 'a;
    
    type ValuesMut: Iterator<Item = &'a mut Self::_Value> + 'a;
}

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

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

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

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

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

    fn values<'a>(&'a self) -> <Self as _ComponentStore<'a>>::Values;

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

// ++++++++++++++++++++ ComponentStoreIter ++++++++++++++++++++

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

    type IterMut: Iterator<Item = (Valid<'a, Self::Id>, &'a mut Self::_Value)> + '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;
}

// ++++++++++++++++++++ EntityStore ++++++++++++++++++++

pub trait EntityStore: StoreBase {
    fn assign<'id>(&mut self, id: Valid<'id, Self::Id>) -> bool;

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

// ++++++++++++++++++++ EntityStoreIter ++++++++++++++++++++

pub trait _EntityStoreIter<'a>: EntityStore {
    type Iter: Iterator<Item = Valid<'a, Self::Id>>;
}

pub trait EntityStoreIter: EntityStore
    where Self: for<'a> _EntityStoreIter<'a>
{
    fn iter<'a>(&'a self) -> <Self as _EntityStoreIter<'a>>::Iter;
}

// ++++++++++++++++++++ StoreWithDirtyState ++++++++++++++++++++

/// * `assign -> Dirtied::Assigned`
/// * `{release, clear} -> Dirtied::Released`
/// * `{get_mut, iter_mut} -> Dirtied::Modified`
/// * `release & assign -> Dirtied::Modified`
/// * `assign & release` -> (nothing)`
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Dirtied<'id, ID: Id> {
    Assigned(Valid<'id, ID>),
    Released(ID),
    Modified(Valid<'id, ID>),
}

impl<'id, ID: Id> Borrow<ID> for Dirtied<'id, ID> {
    fn borrow(&self) -> &ID {
        match self {
            &Dirtied::Assigned(ref id) => &*id,
            &Dirtied::Released(ref id) => &id,
            &Dirtied::Modified(ref id) => &*id,
        }
    }
}

/// Workaround for lack of HK-lifetimes.
pub trait _StoreWithDirtyState<'a>: StoreBase {
    type DirtyEntities: Iterator<Item = Dirtied<'a, Self::Id>>;
}

pub trait StoreWithDirtyState: StoreBase 
    where Self: for<'a> _StoreWithDirtyState<'a>
{
    fn was_cleared(&self) -> bool;

    fn dirty_entities<'a>(&'a self) -> <Self as _StoreWithDirtyState<'a>>::DirtyEntities;
}

// ++++++++++++++++++++ newtype-impls ++++++++++++++++++++

use std::ops::DerefMut;

impl<S> StoreBase for S
    where S: DerefMut + ServiceBase, S::Target: StoreBase
{
    type Id = <S::Target as StoreBase>::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()
    }
}

impl<'a, S> _ComponentStore<'a> for S
    where S: DerefMut + ServiceBase, S::Target: _ComponentStore<'a>
{
    type _Value = <S::Target as _ComponentStore<'a>>::_Value;

    type Values = <S::Target as _ComponentStore<'a>>::Values;
    
    type ValuesMut = <S::Target as _ComponentStore<'a>>::ValuesMut;
}

impl<S> ComponentStore for S
    where S: DerefMut + ServiceBase, S::Target: ComponentStore
{
    type Value = <S::Target as ComponentStore>::Value; 

    fn assign<'id, T>(&mut self, id: Valid<'id, Self::Id>, com: T) -> Option<Self::Value>
        where T: Into<Self::Value>
    {
        (**self).assign(id, com)
    }

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

    fn get<'id>(&self, id: Valid<'id, Self::Id>) -> Option<&Self::Value> {
        (**self).get(id)
    }

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

    fn values<'a>(&'a self) -> <Self as _ComponentStore<'a>>::Values {
        (**self).values()
    }

    fn values_mut<'a>(&'a mut self) -> <Self as _ComponentStore<'a>>::ValuesMut {
        (**self).values_mut()
    }
}

impl<'a, S> _ComponentStoreIter<'a> for S
    where S: DerefMut + ServiceBase, S::Target: _ComponentStoreIter<'a>
{
    type Iter = <S::Target as _ComponentStoreIter<'a>>::Iter;

    type IterMut = <S::Target as _ComponentStoreIter<'a>>::IterMut;
}

impl<S> ComponentStoreIter for S
    where S: DerefMut + ServiceBase, S::Target: ComponentStoreIter
{
    fn iter<'a>(&'a self) -> <Self as _ComponentStoreIter<'a>>::Iter {
        (**self).iter()
    }

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

impl<S> EntityStore for S
    where S: DerefMut + ServiceBase, S::Target: EntityStore
{
    fn assign<'id>(&mut self, id: Valid<'id, Self::Id>) -> bool {
        (**self).assign(id)
    }

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

impl<'a, S> _EntityStoreIter<'a> for S
    where S: DerefMut + ServiceBase, S::Target: _EntityStoreIter<'a>
{
    type Iter = <S::Target as _EntityStoreIter<'a>>::Iter;
}

impl<S> EntityStoreIter for S
    where S: DerefMut + ServiceBase, S::Target: EntityStoreIter
{
    fn iter<'a>(&'a self) -> <Self as _EntityStoreIter<'a>>::Iter {
        (**self).iter()
    }
}

// ++++++++++++++++++++ StoreWithDirtyState ++++++++++++++++++++

impl<'a, S> _StoreWithDirtyState<'a> for S
    where S: DerefMut + ServiceBase, S::Target: _StoreWithDirtyState<'a>
{
    type DirtyEntities = <S::Target as _StoreWithDirtyState<'a>>::DirtyEntities;
}

impl<S> StoreWithDirtyState for S
    where S: DerefMut + ServiceBase, S::Target: StoreWithDirtyState
{
    fn was_cleared<'a>(&self) -> bool {
        (**self).was_cleared()
    }

    fn dirty_entities<'a>(&'a self) -> <Self as _StoreWithDirtyState<'a>>::DirtyEntities {
        (**self).dirty_entities()
    }
}