flecs_ecs 0.2.2

Rust API for the C/CPP flecs ECS library <https://github.com/SanderMertens/flecs>
Documentation
use super::{FlecsArray, FlecsIdMap, World};
use crate::sys;

#[cfg(feature = "std")]
extern crate std;

extern crate alloc;
use alloc::vec;

pub(crate) struct WorldCtx {
    query_ref_count: i32,
    pub(crate) components: FlecsIdMap,
    pub(crate) components_array: FlecsArray,
    is_panicking: bool,
}

impl WorldCtx {
    pub(crate) fn new() -> Self {
        Self {
            query_ref_count: 0,
            components: Default::default(),
            components_array: vec![0; 500],
            is_panicking: false,
        }
    }

    pub(crate) fn inc_query_ref_count(&mut self) {
        unsafe {
            if sys::ecs_os_has_threading() {
                if let Some(ainc) = sys::ecs_os_api.ainc_ {
                    ainc(&mut self.query_ref_count);
                }
            } else {
                self.query_ref_count += 1;
            }
        }
    }

    pub(crate) fn dec_query_ref_count(&mut self) {
        unsafe {
            if sys::ecs_os_has_threading() {
                if let Some(adec) = sys::ecs_os_api.adec_ {
                    adec(&mut self.query_ref_count);
                }
            } else {
                self.query_ref_count -= 1;
            }
        }
    }

    #[allow(dead_code)] //used in tests
    pub(crate) fn query_ref_count(&self) -> i32 {
        self.query_ref_count
    }

    pub(crate) fn is_ref_count_zero(&self) -> bool {
        self.query_ref_count == 0
    }

    pub(crate) fn set_is_panicking_true(&mut self) {
        self.is_panicking = true;
    }

    pub(crate) fn is_panicking(&self) -> bool {
        self.is_panicking || std::thread::panicking()
    }
}

impl World {
    #[allow(dead_code)] //used in tests
    pub(crate) fn world_ctx(&self) -> &WorldCtx {
        unsafe { &*(sys::ecs_get_binding_ctx(self.raw_world.as_ptr()) as *const WorldCtx) }
    }

    #[allow(clippy::mut_from_ref)]
    pub(crate) fn world_ctx_mut(&self) -> &mut WorldCtx {
        unsafe { &mut *(sys::ecs_get_binding_ctx(self.raw_world.as_ptr()) as *mut WorldCtx) }
    }
}

#[test]
fn query_ref_count() {
    unsafe {
        flecs_ecs::sys::ecs_os_init();
    }
    use flecs_ecs::core::*;
    use flecs_ecs::macros::*;

    #[derive(Component)]
    struct Tag;

    let world = World::new();
    let query = world.query::<()>().with(Tag).build();

    assert_eq!(world.world_ctx().query_ref_count(), 1);
    assert_eq!(query.reference_count(), 1);

    let query2 = query.clone();

    assert_eq!(world.world_ctx().query_ref_count(), 2);
    assert_eq!(query.reference_count(), 2);

    drop(query);

    assert_eq!(world.world_ctx().query_ref_count(), 1);
    assert_eq!(query2.reference_count(), 1);

    drop(query2);

    assert_eq!(world.world_ctx().query_ref_count(), 0);
}