bevy_mod_ffi_guest 0.2.0

FFI utilities for Bevy guests
Documentation
use super::{ParamBuilder, ParamCursor};
use crate::{
    query::{Query, QueryData, QueryFilter},
    world::World,
};
use bevy_mod_ffi_core::query;
use bevy_mod_ffi_guest_sys;
use std::ptr;

#[allow(clippy::missing_safety_doc)]
pub unsafe trait SystemParam {
    type State: 'static;

    type Item<'w, 's>;

    fn build(world: &mut World, builder: &mut ParamBuilder) -> Self::State;

    unsafe fn get_param<'w, 's>(
        state: &'s mut Self::State,
        cursor: &mut ParamCursor<'_>,
    ) -> Self::Item<'w, 's>;
}

unsafe impl SystemParam for () {
    type State = ();
    type Item<'w, 's> = ();

    fn build(_world: &mut World, _builder: &mut ParamBuilder) {}

    unsafe fn get_param<'w, 's>(
        state: &'s mut Self::State,
        cursor: &mut ParamCursor<'_>,
    ) -> Self::Item<'w, 's> {
        let _ = state;
        let _ = cursor;
    }
}

unsafe impl<D, F> SystemParam for Query<'_, '_, D, F>
where
    D: QueryData + 'static,
    F: QueryFilter + 'static,
{
    type State = D::State;
    type Item<'w, 's> = Query<'w, 's, D, F>;

    fn build(world: &mut World, builder: &mut ParamBuilder) -> Self::State {
        builder.add_query::<D, F>(world);
        D::build_state(world)
    }

    unsafe fn get_param<'w, 's>(
        state: &'s mut Self::State,
        cursor: &mut ParamCursor<'_>,
    ) -> Self::Item<'w, 's> {
        let dyn_param_ptr = cursor.next().unwrap();
        let mut query_ptr: *mut query = ptr::null_mut();
        let success = unsafe {
            bevy_mod_ffi_guest_sys::system::param::bevy_dyn_system_param_downcast_query(
                dyn_param_ptr,
                &mut query_ptr,
            )
        };
        if !success || query_ptr.is_null() {
            panic!("Failed to downcast DynSystemParam to Query");
        }
        Query::new(query_ptr, state)
    }
}

macro_rules! impl_system_param_tuple {
    ($($param:ident),*) => {
        #[allow(non_snake_case)]
        unsafe impl<$($param: SystemParam,)*> SystemParam for ($($param,)*) {
            type State = ($($param::State,)*);
            type Item<'w, 's> = ($($param::Item<'w, 's>,)*);

            fn build(world: &mut World, builder: &mut ParamBuilder) -> Self::State {
                ($($param::build(world, builder),)*)
            }

            unsafe fn get_param<'w, 's>(
                state: &'s mut Self::State,
                cursor: &mut ParamCursor<'_>,
            ) -> Self::Item<'w, 's> {
                let ($($param,)*) = state;
                unsafe { ($($param::get_param($param, cursor),)*) }
            }
        }
    };
}

impl_system_param_tuple!(P0);
impl_system_param_tuple!(P0, P1);
impl_system_param_tuple!(P0, P1, P2);
impl_system_param_tuple!(P0, P1, P2, P3);
impl_system_param_tuple!(P0, P1, P2, P3, P4);
impl_system_param_tuple!(P0, P1, P2, P3, P4, P5);
impl_system_param_tuple!(P0, P1, P2, P3, P4, P5, P6);
impl_system_param_tuple!(P0, P1, P2, P3, P4, P5, P6, P7);