goud_engine/component_ops/
batch_ops.rs1use std::collections::HashMap;
7
8use crate::context_registry::{GoudContextId, GOUD_INVALID_CONTEXT_ID};
9use crate::core::error::{set_last_error, GoudError};
10
11use super::helpers::context_key;
12use super::storage::{get_context_storage_map, get_type_registry};
13
14pub unsafe fn component_add_batch_impl(
22 context_id: GoudContextId,
23 entity_ids: *const u64,
24 count: u32,
25 type_id_hash: u64,
26 data_ptr: *const u8,
27 component_size: usize,
28) -> u32 {
29 if context_id == GOUD_INVALID_CONTEXT_ID {
30 set_last_error(GoudError::InvalidContext);
31 return 0;
32 }
33
34 if entity_ids.is_null() {
35 set_last_error(GoudError::InvalidState(
36 "entity_ids pointer is null".to_string(),
37 ));
38 return 0;
39 }
40
41 if data_ptr.is_null() {
42 set_last_error(GoudError::InvalidState(
43 "data_ptr pointer is null".to_string(),
44 ));
45 return 0;
46 }
47
48 if count == 0 {
49 return 0;
50 }
51
52 let type_info = {
53 let type_registry = get_type_registry();
54 let registry_map = match type_registry.as_ref() {
55 Some(map) => map,
56 None => {
57 set_last_error(GoudError::ResourceNotFound(format!(
58 "Component type {} not registered",
59 type_id_hash
60 )));
61 return 0;
62 }
63 };
64 match registry_map.get(&type_id_hash) {
65 Some(info) => info.clone(),
66 None => {
67 set_last_error(GoudError::ResourceNotFound(format!(
68 "Component type {} not registered",
69 type_id_hash
70 )));
71 return 0;
72 }
73 }
74 };
75
76 if component_size != type_info.size {
77 set_last_error(GoudError::InvalidState(format!(
78 "Component size mismatch: expected {}, got {}",
79 type_info.size, component_size
80 )));
81 return 0;
82 }
83
84 let mut storage_map = get_context_storage_map();
85 let map = storage_map.get_or_insert_with(HashMap::new);
86
87 let key = context_key(context_id);
88 let context_storage = map.entry(key).or_default();
89 let storage =
90 context_storage.get_or_create_storage(type_id_hash, type_info.size, type_info.align);
91
92 let entity_slice = std::slice::from_raw_parts(entity_ids, count as usize);
94 let mut success_count = 0u32;
95
96 for (i, &entity_bits) in entity_slice.iter().enumerate() {
97 let component_data = data_ptr.add(i * component_size);
98 if storage.insert(entity_bits, component_data) {
99 success_count += 1;
100 }
101 }
102
103 success_count
104}
105
106pub unsafe fn component_remove_batch_impl(
112 context_id: GoudContextId,
113 entity_ids: *const u64,
114 count: u32,
115 type_id_hash: u64,
116) -> u32 {
117 if context_id == GOUD_INVALID_CONTEXT_ID {
118 set_last_error(GoudError::InvalidContext);
119 return 0;
120 }
121
122 if entity_ids.is_null() {
123 set_last_error(GoudError::InvalidState(
124 "entity_ids pointer is null".to_string(),
125 ));
126 return 0;
127 }
128
129 if count == 0 {
130 return 0;
131 }
132
133 {
134 let type_registry = get_type_registry();
135 let registry_map = match type_registry.as_ref() {
136 Some(map) => map,
137 None => {
138 set_last_error(GoudError::ResourceNotFound(format!(
139 "Component type {} not registered",
140 type_id_hash
141 )));
142 return 0;
143 }
144 };
145 if !registry_map.contains_key(&type_id_hash) {
146 set_last_error(GoudError::ResourceNotFound(format!(
147 "Component type {} not registered",
148 type_id_hash
149 )));
150 return 0;
151 }
152 }
153
154 let mut storage_map = get_context_storage_map();
155 let map = match storage_map.as_mut() {
156 Some(m) => m,
157 None => return 0,
158 };
159
160 let key = context_key(context_id);
161 let context_storage = match map.get_mut(&key) {
162 Some(s) => s,
163 None => return 0,
164 };
165
166 let storage = match context_storage.get_storage_mut(type_id_hash) {
167 Some(s) => s,
168 None => return 0,
169 };
170
171 let entity_slice = std::slice::from_raw_parts(entity_ids, count as usize);
173 let mut success_count = 0u32;
174
175 for &entity_bits in entity_slice {
176 if storage.remove(entity_bits) {
177 success_count += 1;
178 }
179 }
180
181 success_count
182}
183
184pub unsafe fn component_has_batch_impl(
191 context_id: GoudContextId,
192 entity_ids: *const u64,
193 count: u32,
194 type_id_hash: u64,
195 out_results: *mut u8,
196) -> u32 {
197 if context_id == GOUD_INVALID_CONTEXT_ID {
198 set_last_error(GoudError::InvalidContext);
199 return 0;
200 }
201
202 if entity_ids.is_null() {
203 set_last_error(GoudError::InvalidState(
204 "entity_ids pointer is null".to_string(),
205 ));
206 return 0;
207 }
208
209 if out_results.is_null() {
210 set_last_error(GoudError::InvalidState(
211 "out_results pointer is null".to_string(),
212 ));
213 return 0;
214 }
215
216 if count == 0 {
217 return 0;
218 }
219
220 {
221 let type_registry = get_type_registry();
222 let registry_map = match type_registry.as_ref() {
223 Some(map) => map,
224 None => {
225 set_last_error(GoudError::ResourceNotFound(format!(
226 "Component type {} not registered",
227 type_id_hash
228 )));
229 return 0;
230 }
231 };
232 if !registry_map.contains_key(&type_id_hash) {
233 set_last_error(GoudError::ResourceNotFound(format!(
234 "Component type {} not registered",
235 type_id_hash
236 )));
237 return 0;
238 }
239 }
240
241 let storage_map = get_context_storage_map();
242
243 let storage_exists = storage_map.as_ref().is_some_and(|map| {
244 let key = context_key(context_id);
245 map.get(&key)
246 .and_then(|cs| cs.get_storage(type_id_hash))
247 .is_some()
248 });
249
250 let entity_slice = std::slice::from_raw_parts(entity_ids, count as usize);
252 let results_slice = std::slice::from_raw_parts_mut(out_results, count as usize);
253
254 if !storage_exists {
255 for result in results_slice.iter_mut() {
256 *result = 0;
257 }
258 return count;
259 }
260
261 let map = storage_map.as_ref().unwrap();
262 let key = context_key(context_id);
263 let context_storage = map.get(&key).unwrap();
264 let storage = context_storage.get_storage(type_id_hash).unwrap();
265
266 for (i, &entity_bits) in entity_slice.iter().enumerate() {
267 results_slice[i] = if storage.contains(entity_bits) { 1 } else { 0 };
268 }
269
270 count
271}