ecsilarant 0.1.0

Sketch of an ECS for the future
Documentation
use crate::cons::{Cons, Empty};
use crate::storage::world_storage::archetype_storage::ArchetypeToStorage;
use crate::storage::world_storage::archetype_storage::index_deduct::IndexDeduct;
use crate::storage::world_storage::archetype_storage::ordered_selection::OrderedSelector;
use archetype_storage::{ArchetypeStorage, IterSeq};
use std::fmt::Debug;

mod archetype_storage;

trait WorldStorage<'a>: Sized {
    type ExtendedWorldStorage<Archetype: ArchetypeToStorage<'a>>: WorldStorage<'a>;
    fn add_archetype_storage<Archetype: ArchetypeToStorage<'a>>(
        self,
    ) -> Self::ExtendedWorldStorage<Archetype>;
    fn query<Query>(&'a mut self) -> <Self as WorldStorageQuery<'a, Query>>::Result
    where
        Self: WorldStorageQuery<'a, Query>,
    {
        WorldStorageQuery::<'a, Query>::recursive_query(self)
    }
}

type WorldStorageData<Head, Tail> = Cons<Head, Tail>;

impl<'a, Head, Tail: WorldStorage<'a>> WorldStorage<'a> for WorldStorageData<Head, Tail> {
    type ExtendedWorldStorage<Archetype: ArchetypeToStorage<'a>> = WorldStorageData<
        <Archetype as ArchetypeToStorage<'a>>::ArchetypeStorageType,
        WorldStorageData<Head, Tail>,
    >;

    fn add_archetype_storage<Archetype: ArchetypeToStorage<'a>>(
        self,
    ) -> Self::ExtendedWorldStorage<Archetype> {
        WorldStorageData {
            head: <Archetype as ArchetypeToStorage>::ArchetypeStorageType::new(),
            tail: self,
        }
    }
}

impl<'a> WorldStorage<'a> for Empty {
    type ExtendedWorldStorage<Archetype: ArchetypeToStorage<'a>> =
        WorldStorageData<<Archetype as ArchetypeToStorage<'a>>::ArchetypeStorageType, Empty>;

    fn add_archetype_storage<Archetype: ArchetypeToStorage<'a>>(
        self,
    ) -> Self::ExtendedWorldStorage<Archetype> {
        WorldStorageData {
            head: <Archetype as ArchetypeToStorage>::ArchetypeStorageType::new(),
            tail: self,
        }
    }
}

trait Create<'a, Query, Producer> {
    fn create(value: &'a mut Producer) -> Self;
}

#[derive(Debug)]
struct RecursiveResultWrapper<'a, Tail, Query>
where
    Tail: WorldStorageQuery<'a, Query>,
{
    value: <Tail as WorldStorageQuery<'a, Query>>::Result,
}

impl<'a, AStorage: ArchetypeStorage<'a>, Tail: WorldStorageQuery<'a, Query>, Query>
    Create<'a, Query, WorldStorageData<AStorage, Tail>>
    for RecursiveResultWrapper<'a, Tail, Query>
{
    fn create(value: &'a mut WorldStorageData<AStorage, Tail>) -> Self {
        RecursiveResultWrapper {
            value: <Tail as WorldStorageQuery<'a, Query>>::recursive_query(&mut value.tail),
        }
    }
}

impl<'a, AStorage: ArchetypeStorage<'a>, Tail: WorldStorageQuery<'a, Query>, Query>
    Create<'a, Query, WorldStorageData<AStorage, Tail>>
    for Cons<
        <AStorage as OrderedSelector<
            'a,
            Query,
            <AStorage::Archetype as IndexDeduct<'a, Query>>::Index,
        >>::Result,
        <Tail as WorldStorageQuery<'a, Query>>::Result,
    >
where
    AStorage::Archetype: IndexDeduct<'a, Query>,
    AStorage: OrderedSelector<'a, Query, <AStorage::Archetype as IndexDeduct<'a, Query>>::Index>,
{
    fn create(value: &'a mut WorldStorageData<AStorage, Tail>) -> Self {
        Cons {
            head: value.head.get_many_ordered(),
            tail: value.tail.recursive_query(),
        }
    }
}

impl<'a, Query> Create<'a, Query, Empty> for Empty {
    fn create(value: &'a mut Empty) -> Self {
        Empty {}
    }
}

trait WorldStorageQuery<'a, Query>: Sized {
    type Result: Create<'a, Query, Self> + Debug;
    fn recursive_query(&'a mut self) -> Self::Result;
}

impl<'a, Query: Debug, AStorage: ArchetypeStorage<'a>, Tail: WorldStorageQuery<'a, Query> + Debug>
    WorldStorageQuery<'a, Query> for WorldStorageData<AStorage, Tail>
{
    default type Result = RecursiveResultWrapper<'a, Tail, Query>;

    #[inline(always)]
    default fn recursive_query(&'a mut self) -> Self::Result {
        Self::Result::create(self)
    }
}

impl<'a, Query: Debug, AStorage: ArchetypeStorage<'a>, Tail: WorldStorageQuery<'a, Query> + Debug>
    WorldStorageQuery<'a, Query> for WorldStorageData<AStorage, Tail>
where
    AStorage::Archetype: IndexDeduct<'a, Query>,
    AStorage: OrderedSelector<'a, Query, <AStorage::Archetype as IndexDeduct<'a, Query>>::Index>,
{
    type Result = Cons<
        <AStorage as OrderedSelector<
            'a,
            Query,
            <AStorage::Archetype as IndexDeduct<'a, Query>>::Index,
        >>::Result,
        <Tail as WorldStorageQuery<'a, Query>>::Result,
    >;

    #[inline(always)]
    fn recursive_query(&'a mut self) -> Self::Result {
        Cons {
            head: self.head.get_many_ordered(),
            tail: <Tail as WorldStorageQuery<'a, Query>>::recursive_query(&mut self.tail),
        }
    }
}

impl<'a, Query> WorldStorageQuery<'a, Query> for Empty {
    type Result = Empty;

    fn recursive_query(&'a mut self) -> Self::Result {
        Empty {}
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::cons::Empty;
    use crate::cons::{Cons, Seq};
    use crate::storage::world_storage::archetype_storage::{ArchetypeSoa, create_storage};

    #[test]
    fn order_select() {
        type A<'a> = Cons<u8, Cons<u16, Empty>>;
        let archetype_a: A = Empty {}.extend(1u16).extend(2u8);
        let mut archetype_storage_a = create_storage::<A>();

        type B<'a> = Cons<u32, Cons<u16, Empty>>;
        let archetype_b: B = Empty {}.extend(3u16).extend(4u32);
        let mut archetype_storage_b = create_storage::<B>();

        type WA<'a> = WorldStorageData<ArchetypeSoa<'a, u8, ArchetypeSoa<'a, u16, Empty>>, Empty>;

        let mut world: WA = Empty.add_archetype_storage::<A>();
        world.head.insert(archetype_a);

        {
            let mut result = world.query::<Cons<&u8, Empty>>();
            println!("{:?}", result);
            assert_eq!(result.head.head.next().unwrap(), &2u8)
        }

        type WB<'a> = WorldStorageData<ArchetypeSoa<'a, u32, ArchetypeSoa<'a, u16, Empty>>, WA<'a>>;

        let mut next_world: WB = world.add_archetype_storage::<B>();
        next_world.head.insert(archetype_b);

        let mut result = next_world.query::<Cons<&u8, Empty>>();
        println!("{:?}", result);
    }
}