bevy_spliff 0.1.0

A crate for doing joins in bevy.
Documentation
use crate::prelude::*;
use bevy_ecs::{
    prelude::*,
    query::{EcsAccessType, QueryData, ReadOnlyQueryData, WorldQuery},
    storage::TableRow,
};

unsafe impl<Ref, Data> ReadOnlyQueryData for Joined<Ref, Data>
where
    Ref: Joinable + Component,
    Data: ReadOnlyQueryData,
    <Data as WorldQuery>::State: Clone,
{
}

unsafe impl<Ref, Data> QueryData for Joined<Ref, Data>
where
    Ref: Joinable + Component,
    Data: ReadOnlyQueryData,
    <Data as WorldQuery>::State: Clone,
{
    const IS_READ_ONLY: bool = true;
    const IS_ARCHETYPAL: bool = false;

    type ReadOnly = Self;
    type Item<'w, 's> = <Ref::Mapper as JoinResultMapper>::Item<'w, 's, Data>;

    fn shrink<'wlong: 'wshort, 'wshort, 's>(
        item: Self::Item<'wlong, 's>,
    ) -> Self::Item<'wshort, 's> {
        <Ref::Mapper as JoinResultMapper>::shrink::<'wlong, 'wshort, 's, Data>(item)
    }

    unsafe fn fetch<'w, 's>(
        state: &'s Self::State,
        fetch: &mut Self::Fetch<'w>,
        entity: Entity,
        _table_row: TableRow,
    ) -> Option<Self::Item<'w, 's>> {
        unsafe {
            let mut data_fetch = Data::init_fetch(
                fetch.world,
                &state.target_state,
                fetch.world.last_change_tick(),
                fetch.world.change_tick(),
            );

            let res = fetch
                .iter_joined(entity)?
                .map(|(target, cell)| {
                    let location = cell.location();
                    let tables = fetch.world.storages().tables.get(location.table_id)?;
                    let archetype = fetch.world.archetypes().get(location.archetype_id)?;

                    Some(
                        Data::matches_component_set(&state.target_state, &|id| {
                            archetype.contains(id)
                        })
                        .then(|| {
                            Data::set_archetype(
                                &mut data_fetch,
                                &state.target_state,
                                archetype,
                                tables,
                            );

                            Data::fetch(
                                &state.target_state,
                                &mut data_fetch,
                                target,
                                location.table_row,
                            )
                        })
                        .flatten(),
                    )
                })
                .collect::<Option<Vec<_>>>()?
                .into_iter()
                .flatten()
                .collect();

            Some(Ref::Mapper::map_results(res))
        }
    }
    #[inline(always)]
    fn iter_access(state: &Self::State) -> impl Iterator<Item = EcsAccessType<'_>> {
        state.iter_access()
    }
}