yaks 0.1.0

Minimalistic framework for automatic multithreading of hecs via rayon
Documentation
use hecs::{Component, Query, With, Without};

#[cfg(feature = "parallel")]
use hecs::World;
#[cfg(feature = "parallel")]
use std::any::TypeId;

use crate::QueryMarker;

#[cfg(feature = "parallel")]
use crate::{ArchetypeSet, ComponentTypeSet};

pub trait QueryExt: Query {
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet);

    #[cfg(feature = "parallel")]
    fn set_archetype_bits(world: &World, archetype_set: &mut ArchetypeSet)
    where
        Self: Sized,
    {
        archetype_set.set_bits_for_query::<Self>(world);
    }
}

pub trait QueryBundle {
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize;

    fn markers() -> Self;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet);

    #[cfg(feature = "parallel")]
    fn set_archetype_bits(world: &World, archetype_set: &mut ArchetypeSet);
}

impl QueryExt for () {
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = 0;

    #[cfg(feature = "parallel")]
    fn insert_component_types(_: &mut ComponentTypeSet) {}
}

impl QueryBundle for () {
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = 0;

    fn markers() -> Self {}

    #[cfg(feature = "parallel")]
    fn insert_component_types(_: &mut ComponentTypeSet) {}

    #[cfg(feature = "parallel")]
    fn set_archetype_bits(_: &World, _: &mut ArchetypeSet) {}
}

impl<C0> QueryExt for &'_ C0
where
    C0: Component,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = 1;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        component_type_set.immutable.insert(TypeId::of::<C0>());
    }
}

impl<C0> QueryExt for &'_ mut C0
where
    C0: Component,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = 1;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        component_type_set.mutable.insert(TypeId::of::<C0>());
    }
}

impl<Q0> QueryExt for Option<Q0>
where
    Q0: QueryExt,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = Q0::COMPONENT_TYPE_SET_LENGTH;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        Q0::insert_component_types(component_type_set);
    }
}

impl<C0, Q0> QueryExt for With<C0, Q0>
where
    C0: Component,
    Q0: QueryExt,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = Q0::COMPONENT_TYPE_SET_LENGTH;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        Q0::insert_component_types(component_type_set);
    }
}

impl<C0, Q0> QueryExt for Without<C0, Q0>
where
    C0: Component,
    Q0: QueryExt,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = Q0::COMPONENT_TYPE_SET_LENGTH;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        Q0::insert_component_types(component_type_set);
    }
}

impl<Q0> QueryBundle for QueryMarker<Q0>
where
    Q0: QueryExt,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = Q0::COMPONENT_TYPE_SET_LENGTH;

    fn markers() -> Self {
        QueryMarker::new()
    }

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        Q0::insert_component_types(component_type_set);
    }

    #[cfg(feature = "parallel")]
    fn set_archetype_bits(world: &World, archetype_set: &mut ArchetypeSet) {
        Q0::set_archetype_bits(world, archetype_set);
    }
}

impl<Q0> QueryExt for (Q0,)
where
    Q0: QueryExt,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = Q0::COMPONENT_TYPE_SET_LENGTH;

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        Q0::insert_component_types(component_type_set);
    }
}

impl<Q0> QueryBundle for (QueryMarker<Q0>,)
where
    Q0: Query + QueryExt,
{
    #[cfg(feature = "parallel")]
    const COMPONENT_TYPE_SET_LENGTH: usize = Q0::COMPONENT_TYPE_SET_LENGTH;

    fn markers() -> Self {
        (QueryMarker::new(),)
    }

    #[cfg(feature = "parallel")]
    fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
        Q0::insert_component_types(component_type_set);
    }

    #[cfg(feature = "parallel")]
    fn set_archetype_bits(world: &World, archetype_set: &mut ArchetypeSet) {
        Q0::set_archetype_bits(world, archetype_set);
    }
}

macro_rules! impl_query_single {
    ($($letter:ident),*) => {
        impl<$($letter),*> QueryExt for ($($letter,)*)
        where
            $($letter: QueryExt,)*
        {
            #[cfg(feature = "parallel")]
            const COMPONENT_TYPE_SET_LENGTH: usize = 0 $(+ $letter::COMPONENT_TYPE_SET_LENGTH)*;

            #[cfg(feature = "parallel")]
            fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
                $($letter::insert_component_types(component_type_set);)*
            }
        }
    }
}

impl_for_tuples!(impl_query_single);

macro_rules! impl_query_bundle {
    ($($letter:ident),*) => {
        impl<$($letter),*> QueryBundle for ($(QueryMarker<$letter>,)*)
        where
            $($letter: Query + QueryExt,)*
        {
            #[cfg(feature = "parallel")]
            const COMPONENT_TYPE_SET_LENGTH: usize = 0 $(+ $letter::COMPONENT_TYPE_SET_LENGTH)*;

            fn markers() -> Self {
                ($(QueryMarker::<$letter>::new(),)*)
            }

            #[cfg(feature = "parallel")]
            fn insert_component_types(component_type_set: &mut ComponentTypeSet) {
                $($letter::insert_component_types(component_type_set);)*
            }

            #[cfg(feature = "parallel")]
            fn set_archetype_bits(world: &World, archetype_set: &mut ArchetypeSet) {
                $($letter::set_archetype_bits(world, archetype_set);)*
            }
        }
    }
}

impl_for_tuples!(impl_query_bundle);