Skip to main content

goud_engine/sdk/
component_ops.rs

1//! # SDK Generic Component Operations API
2//!
3//! Provides static functions for type-erased component operations: register,
4//! add, remove, has, get, get_mut, and batch variants. These are annotated
5//! with `#[goud_api]` to auto-generate FFI wrappers that replace the
6//! hand-written functions in `ffi/component.rs`.
7//!
8//! All methods are static (no `self` receiver) because they operate on the
9//! global per-context component storage, not on a GoudGame instance.
10//!
11//! The raw component storage and type registry internals remain in
12//! `ffi/component.rs` and are accessed via public helper functions.
13
14use crate::component_ops::{
15    component_add_batch_impl, component_add_impl, component_get_impl, component_get_mut_impl,
16    component_has_batch_impl, component_has_impl, component_register_type_impl,
17    component_remove_batch_impl, component_remove_impl,
18};
19use crate::context_registry::GoudContextId;
20use crate::core::types::{GoudEntityId, GoudResult};
21
22/// Zero-sized type hosting generic component FFI operations.
23pub struct ComponentOps;
24
25// NOTE: FFI wrappers are hand-written in ffi/component.rs. The `#[goud_api]`
26// attribute is omitted here to avoid duplicate `#[no_mangle]` symbol conflicts.
27impl ComponentOps {
28    /// Registers a component type with the engine.
29    ///
30    /// # Safety
31    ///
32    /// - `name_ptr` must be a valid pointer to UTF-8 data (or null)
33    /// - `size` and `align` must match the actual type layout
34    pub unsafe fn register_type(
35        type_id_hash: u64,
36        name_ptr: *const u8,
37        name_len: usize,
38        size: usize,
39        align: usize,
40    ) -> bool {
41        component_register_type_impl(type_id_hash, name_ptr, name_len, size, align)
42    }
43
44    /// Adds a component to an entity.
45    ///
46    /// # Safety
47    ///
48    /// - `data_ptr` must point to valid component data
49    /// - `data_size` must match the registered component size
50    pub unsafe fn add(
51        context_id: GoudContextId,
52        entity_id: GoudEntityId,
53        type_id_hash: u64,
54        data_ptr: *const u8,
55        data_size: usize,
56    ) -> GoudResult {
57        component_add_impl(context_id, entity_id, type_id_hash, data_ptr, data_size)
58    }
59
60    /// Removes a component from an entity.
61    pub fn remove(
62        context_id: GoudContextId,
63        entity_id: GoudEntityId,
64        type_id_hash: u64,
65    ) -> GoudResult {
66        component_remove_impl(context_id, entity_id, type_id_hash)
67    }
68
69    /// Checks if an entity has a specific component.
70    pub fn has(context_id: GoudContextId, entity_id: GoudEntityId, type_id_hash: u64) -> bool {
71        component_has_impl(context_id, entity_id, type_id_hash)
72    }
73
74    /// Gets a read-only pointer to a component on an entity.
75    pub fn get(context_id: GoudContextId, entity_id: GoudEntityId, type_id_hash: u64) -> *const u8 {
76        component_get_impl(context_id, entity_id, type_id_hash)
77    }
78
79    /// Gets a mutable pointer to a component on an entity.
80    pub fn get_mut(
81        context_id: GoudContextId,
82        entity_id: GoudEntityId,
83        type_id_hash: u64,
84    ) -> *mut u8 {
85        component_get_mut_impl(context_id, entity_id, type_id_hash)
86    }
87
88    /// Adds the same component type to multiple entities in a batch.
89    ///
90    /// # Safety
91    ///
92    /// - `entity_ids` must point to valid memory with `count` u64 values
93    /// - `data_ptr` must point to `count * component_size` bytes of data
94    pub unsafe fn add_batch(
95        context_id: GoudContextId,
96        entity_ids: *const u64,
97        count: u32,
98        type_id_hash: u64,
99        data_ptr: *const u8,
100        component_size: usize,
101    ) -> u32 {
102        component_add_batch_impl(
103            context_id,
104            entity_ids,
105            count,
106            type_id_hash,
107            data_ptr,
108            component_size,
109        )
110    }
111
112    /// Removes the same component type from multiple entities in a batch.
113    ///
114    /// # Safety
115    ///
116    /// `entity_ids` must point to valid memory with `count` u64 values.
117    pub unsafe fn remove_batch(
118        context_id: GoudContextId,
119        entity_ids: *const u64,
120        count: u32,
121        type_id_hash: u64,
122    ) -> u32 {
123        component_remove_batch_impl(context_id, entity_ids, count, type_id_hash)
124    }
125
126    /// Checks if multiple entities have a specific component type.
127    ///
128    /// # Safety
129    ///
130    /// - `entity_ids` must point to valid memory with `count` u64 values
131    /// - `out_results` must point to valid memory with `count` u8 values
132    pub unsafe fn has_batch(
133        context_id: GoudContextId,
134        entity_ids: *const u64,
135        count: u32,
136        type_id_hash: u64,
137        out_results: *mut u8,
138    ) -> u32 {
139        component_has_batch_impl(context_id, entity_ids, count, type_id_hash, out_results)
140    }
141}