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}