bevy_mod_ffi_guest 0.2.0

FFI utilities for Bevy guests
Documentation
use crate::{
    query::{QueryBuilder, QueryData, QueryFilter},
    world::World,
};
use bevy_mod_ffi_core::{dyn_system_param, param_builder, system_state};
use bevy_mod_ffi_guest_sys;
use std::{mem, ptr};

pub struct ParamBuilder {
    pub(crate) ptr: *mut param_builder,
}

impl ParamBuilder {
    pub fn new() -> Self {
        let mut builder_ptr: *mut param_builder = ptr::null_mut();

        let success = unsafe {
            bevy_mod_ffi_guest_sys::system::param::bevy_param_builder_new(&mut builder_ptr)
        };

        if !success || builder_ptr.is_null() {
            panic!("Failed to create host-side ParamBuilder");
        }

        Self { ptr: builder_ptr }
    }

    pub fn add_query<D: QueryData + 'static, F: QueryFilter + 'static>(
        &mut self,
        world: &mut World,
    ) {
        let query_builder = QueryBuilder::<D, F>::new(world);
        let query_ptr = query_builder.ptr;
        mem::forget(query_builder);

        let success = unsafe {
            bevy_mod_ffi_guest_sys::system::param::bevy_param_builder_add_query(self.ptr, query_ptr)
        };

        if !success {
            panic!("Failed to add query to param builder");
        }
    }

    pub fn add_commands(&mut self) {
        let success = unsafe {
            bevy_mod_ffi_guest_sys::system::param::bevy_param_builder_add_commands(self.ptr)
        };

        if !success {
            panic!("Failed to add commands to param builder");
        }
    }

    pub fn add_deferred_world(&mut self) {
        let success = unsafe {
            bevy_mod_ffi_guest_sys::system::param::bevy_param_builder_add_deferred_world(self.ptr)
        };

        if !success {
            panic!("Failed to add deferred world to param builder");
        }
    }

    pub(crate) fn build(self, world: &mut World) -> *mut system_state {
        let mut state_ptr: *mut system_state = ptr::null_mut();

        let success = unsafe {
            bevy_mod_ffi_guest_sys::system::param::bevy_param_builder_build(
                world.ptr,
                self.ptr,
                &mut state_ptr,
            )
        };
        if !success {
            panic!("Failed to build SystemState from ParamBuilder");
        }

        mem::forget(self);
        state_ptr
    }
}

impl Default for ParamBuilder {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for ParamBuilder {
    fn drop(&mut self) {
        unsafe { bevy_mod_ffi_guest_sys::system::param::bevy_param_builder_drop(self.ptr) };
    }
}

pub struct ParamCursor<'a> {
    data: &'a [*mut dyn_system_param],
    position: usize,
}

impl<'a> ParamCursor<'a> {
    pub fn new(data: &'a [*mut dyn_system_param]) -> Self {
        Self { data, position: 0 }
    }

    pub fn position(&self) -> usize {
        self.position
    }
}

impl Iterator for ParamCursor<'_> {
    type Item = *mut dyn_system_param;

    fn next(&mut self) -> Option<Self::Item> {
        if self.position >= self.data.len() {
            None
        } else {
            let item = self.data[self.position];
            self.position += 1;
            Some(item)
        }
    }
}