bevy_spliff 0.1.2

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

unsafe impl<Ref, Data> QueryData for JoinedFirst<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> = Data::Item<'w, 's>;

    fn shrink<'wlong: 'wshort, 'wshort, 's>(
        item: Self::Item<'wlong, 's>,
    ) -> Self::Item<'wshort, 's> {
        Data::shrink::<'wlong, 'wshort, 's>(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(),
            );

            fetch
                .iter_joined(entity)?
                .try_fold(
                    ControlFlow::Continue(()),
                    |mut flow, (target, target_cell)| {
                        let location = target_cell.location();
                        let (Some(archetype), Some(table)) = (
                            fetch.world.archetypes().get(location.archetype_id),
                            fetch.world.storages().tables.get(location.table_id),
                        ) else {
                            return Some(flow);
                        };

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

                            if let Some(item) = Data::fetch(
                                &state.target_state,
                                &mut data_fetch,
                                target,
                                location.table_row,
                            ) {
                                flow = ControlFlow::Break(item);
                            }
                        }

                        Some(flow)
                    },
                )?
                .break_value()
        }
    }

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

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