1#![allow(incomplete_features)]
5#![feature(specialization)]
6
7#[doc(hidden)]
11pub use paste;
12#[cfg(feature = "rayon")]
13#[doc(hidden)]
14pub use rayon;
15#[cfg(feature = "serde")]
16#[doc(hidden)]
17pub use serde;
18#[doc(hidden)]
19pub use slotmap;
20
21#[doc(hidden)]
22pub trait IsType<T> {
23 const VALUE: bool = false;
24}
25
26impl<A, B> IsType<B> for A {
27 default const VALUE: bool = false;
28}
29
30impl<T> IsType<T> for T {
32 const VALUE: bool = true;
33}
34
35#[doc(hidden)]
37pub trait ErasedArena {
38 fn get(&self, key: slotmap::DefaultKey) -> Option<&dyn std::any::Any>;
39 fn get_mut(&mut self, key: slotmap::DefaultKey) -> Option<&mut dyn std::any::Any>;
40 unsafe fn get_unchecked(&self, key: slotmap::DefaultKey) -> &dyn std::any::Any;
41 unsafe fn get_unchecked_mut(&mut self, key: slotmap::DefaultKey) -> &mut dyn std::any::Any;
42 fn insert(&mut self, value: Box<dyn std::any::Any>) -> slotmap::DefaultKey;
43 fn insert_with_key(
44 &mut self,
45 f: Box<dyn FnOnce(slotmap::DefaultKey) -> Box<dyn std::any::Any>>,
46 ) -> slotmap::DefaultKey;
47 fn remove(&mut self, key: slotmap::DefaultKey) -> Option<Box<dyn std::any::Any>>;
48}
49
50impl<T: 'static> ErasedArena for slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
51 fn get(&self, key: slotmap::DefaultKey) -> Option<&dyn std::any::Any> {
52 self.get(key).map(|e| e as &dyn std::any::Any)
53 }
54
55 fn get_mut(&mut self, key: slotmap::DefaultKey) -> Option<&mut dyn std::any::Any> {
56 self.get_mut(key).map(|e| e as &mut dyn std::any::Any)
57 }
58
59 unsafe fn get_unchecked(&self, key: slotmap::DefaultKey) -> &dyn std::any::Any {
60 unsafe {
61 <slotmap::DenseSlotMap<slotmap::DefaultKey, T>>::get_unchecked(self, key)
62 as &dyn std::any::Any
63 }
64 }
65
66 unsafe fn get_unchecked_mut(&mut self, key: slotmap::DefaultKey) -> &mut dyn std::any::Any {
67 unsafe {
68 <slotmap::DenseSlotMap<slotmap::DefaultKey, T>>::get_unchecked_mut(self, key)
69 as &mut dyn std::any::Any
70 }
71 }
72
73 fn insert(&mut self, value: Box<dyn std::any::Any>) -> slotmap::DefaultKey {
74 self.insert(*value.downcast::<T>().expect("Try mismatch in insert"))
76 }
77
78 fn insert_with_key(
79 &mut self,
80 f: Box<dyn FnOnce(slotmap::DefaultKey) -> Box<dyn std::any::Any>>,
81 ) -> slotmap::DefaultKey {
82 self.insert_with_key(|k| {
84 *f(k)
85 .downcast::<T>()
86 .expect("Type mismatch in insert_with_key")
87 })
88 }
89
90 fn remove(&mut self, key: slotmap::DefaultKey) -> Option<Box<dyn std::any::Any>> {
91 self.remove(key)
92 .map(|v| Box::new(v) as Box<dyn std::any::Any>)
93 }
94}
95
96#[doc(hidden)]
97pub trait ArenaCast<T> {
98 fn cast(&self) -> &slotmap::DenseSlotMap<slotmap::DefaultKey, T>;
99 fn cast_mut(&mut self) -> &mut slotmap::DenseSlotMap<slotmap::DefaultKey, T>;
100}
101
102impl<A, B> ArenaCast<B> for slotmap::DenseSlotMap<slotmap::DefaultKey, A> {
104 default fn cast(&self) -> &slotmap::DenseSlotMap<slotmap::DefaultKey, B> {
105 panic!(
106 "Arena type mismatch: {} cannot be cast to {}",
108 std::any::type_name::<A>(),
109 std::any::type_name::<B>()
110 );
111 }
112
113 default fn cast_mut(&mut self) -> &mut slotmap::DenseSlotMap<slotmap::DefaultKey, B> {
114 panic!(
115 "Arena type mismatch: {} cannot be cast to {}",
117 std::any::type_name::<A>(),
118 std::any::type_name::<B>()
119 );
120 }
121}
122
123impl<T> ArenaCast<T> for slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
125 fn cast(&self) -> &slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
126 self
127 }
128
129 fn cast_mut(&mut self) -> &mut slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
130 self
131 }
132}
133
134#[cfg(feature = "serde")]
136#[doc(hidden)] pub trait SerdeArena<'de> {
138 fn serialize_arena<S>(&self, field_name: &'static str, state: &mut S) -> Result<(), S::Error>
140 where
141 S: serde::ser::SerializeStruct;
142
143 fn deserialize_arena<M>(map: &mut M) -> Result<Self, M::Error>
145 where
146 M: serde::de::MapAccess<'de>,
147 Self: Sized;
148
149 fn from_seq<V>(seq: &mut V, field_name: &str) -> Result<Self, V::Error>
151 where
152 V: serde::de::SeqAccess<'de>,
153 Self: Sized;
154
155 const ACTIVE: bool; }
157
158#[cfg(feature = "serde")]
160impl<'de, T> SerdeArena<'de> for slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
161 default fn serialize_arena<S>(
162 &self,
163 _field_name: &'static str,
164 _state: &mut S,
165 ) -> Result<(), S::Error>
166 where
167 S: serde::ser::SerializeStruct,
168 {
169 Ok(())
170 }
171
172 default fn deserialize_arena<M>(_map: &mut M) -> Result<Self, M::Error>
173 where
174 M: serde::de::MapAccess<'de>,
175 {
176 Ok(slotmap::DenseSlotMap::new())
177 }
178
179 default fn from_seq<V>(_seq: &mut V, _field_name: &str) -> Result<Self, V::Error>
180 where
181 V: serde::de::SeqAccess<'de>,
182 {
183 Ok(slotmap::DenseSlotMap::new())
184 }
185
186 default const ACTIVE: bool = false;
187}
188
189#[cfg(feature = "serde")]
191impl<'de, T> SerdeArena<'de> for slotmap::DenseSlotMap<slotmap::DefaultKey, T>
192where
193 T: serde::Serialize + serde::Deserialize<'de>,
194{
195 fn serialize_arena<S>(&self, field_name: &'static str, state: &mut S) -> Result<(), S::Error>
196 where
197 S: serde::ser::SerializeStruct,
198 {
199 state.serialize_field(field_name, self)
200 }
201
202 fn deserialize_arena<M>(map: &mut M) -> Result<Self, M::Error>
203 where
204 M: serde::de::MapAccess<'de>,
205 {
206 map.next_value()
207 }
208
209 fn from_seq<V>(seq: &mut V, field_name: &str) -> Result<Self, V::Error>
210 where
211 V: serde::de::SeqAccess<'de>,
212 {
213 seq.next_element()?
214 .ok_or_else(|| serde::de::Error::custom(format!("Missing element for {}", field_name)))
215 }
216
217 const ACTIVE: bool = true;
218}
219
220#[macro_export]
221#[cfg(not(feature = "rayon"))]
222macro_rules! __world_define_rayon_trait_helpers {
223 ($struct_name:ident $( $trait_name:ident ),*) => {};
224}
225
226#[macro_export]
227#[cfg(feature = "rayon")]
228macro_rules! __world_define_rayon_trait_helpers {
229 ($struct_name:ident $( $trait_name:ident ),*) => {
230 $crate::paste::paste! {
231
232$(
233trait [<$struct_name ParVisitIf $trait_name>]<T> {
234 fn pv_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
235 where
236 F: Fn(&dyn $trait_name) + Send + Sync;
237
238 fn pvm_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
239 where
240 F: Fn(&mut dyn $trait_name) + Send + Sync;
241
242 fn pvk_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
243 where
244 F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name) + Send + Sync;
245
246 fn pvkm_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
247 where
248 F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name) + Send + Sync;
249
250 fn pr_if_applicable<P>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, predicate: &P)
251 where
252 P: Fn(&mut dyn $trait_name) -> bool + Send + Sync;
253
254 fn pd_if_applicable<D, F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F, out: &mut [std::mem::MaybeUninit<D>])
255 where
256 D: Send,
257 F: Fn(&dyn $trait_name) -> D + Send + Sync;
258
259 fn pdm_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F, out: &mut [std::mem::MaybeUninit<D>])
260 where
261 D: Send,
262 F: Fn(&mut dyn $trait_name) -> D + Send + Sync;
263
264 fn pda_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F, i: &[D])
266 where
267 D: Sync,
268 F: Fn(&mut dyn $trait_name, &D) + Send + Sync;
269
270 const ACTIVE: bool;
271}
272
273impl<T> [<$struct_name ParVisitIf $trait_name>]<T> for () {
274 default fn pv_if_applicable<F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F)
275 where F: Fn(&dyn $trait_name) + Send + Sync {}
276
277 default fn pvm_if_applicable<F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F)
278 where F: Fn(&mut dyn $trait_name) + Send + Sync {}
279
280 default fn pvk_if_applicable<F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F)
281 where F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name) + Send + Sync {}
282
283 default fn pvkm_if_applicable<F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F)
284 where F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name) + Send + Sync {}
285
286 default fn pr_if_applicable<P>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _predicate: &P)
287 where P: Fn(&mut dyn $trait_name) -> bool + Send + Sync {}
288
289 default fn pd_if_applicable<D, F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F, _out: &mut [std::mem::MaybeUninit<D>])
290 where
291 D: Send,
292 F: Fn(&dyn $trait_name) -> D + Send + Sync {}
293
294 default fn pdm_if_applicable<D, F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F, _out: &mut [std::mem::MaybeUninit<D>])
295 where
296 D: Send,
297 F: Fn(&mut dyn $trait_name) -> D + Send + Sync {}
298
299 default fn pda_if_applicable<D, F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F, _i: &[D])
300 where
301 D: Sync,
302 F: Fn(&mut dyn $trait_name, &D) + Send + Sync {}
303
304 default const ACTIVE: bool = false;
305}
306
307impl<T> [<$struct_name ParVisitIf $trait_name>]<T> for ()
308where
309 T: $trait_name + Send + Sync,
310{
311 fn pv_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
312 where F: Fn(&dyn $trait_name) + Send + Sync
313 {
314 use $crate::rayon::iter::IntoParallelRefIterator;
315 use $crate::rayon::iter::ParallelIterator;
316 arena
317 .values_as_slice()
318 .par_iter()
319 .for_each(|entity| handler(entity));
320 }
321
322 fn pvm_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
323 where F: Fn(&mut dyn $trait_name) + Send + Sync
324 {
325 use $crate::rayon::iter::IntoParallelRefMutIterator;
326 use $crate::rayon::iter::ParallelIterator;
327 arena
328 .values_as_mut_slice()
329 .par_iter_mut()
330 .for_each(|entity| handler(entity));
331 }
332
333 fn pvk_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
334 where F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name) + Send + Sync
335 {
336 use $crate::rayon::iter::IntoParallelRefIterator;
337 use $crate::rayon::iter::IndexedParallelIterator;
338 use $crate::rayon::iter::ParallelIterator;
339 let keys = arena.keys_as_slice();
340 let values = arena.values_as_slice();
341 keys.par_iter()
342 .zip(values.par_iter())
343 .for_each(|(k, v)| handler(($struct_name::arena_id::<T>(), *k), v));
344 }
345
346 fn pvkm_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
347 where F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name) + Send + Sync
348 {
349 use $crate::rayon::iter::IntoParallelRefIterator;
350 use $crate::rayon::iter::IntoParallelRefMutIterator;
351 use $crate::rayon::iter::IndexedParallelIterator;
352 use $crate::rayon::iter::ParallelIterator;
353 let (keys, values) = arena.keys_values_as_mut_slices();
354 keys.par_iter()
355 .zip(values.par_iter_mut())
356 .for_each(|(k, v)| handler(($struct_name::arena_id::<T>(), *k), v));
357 }
358
359 fn pr_if_applicable<P>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, predicate: &P)
360 where P: Fn(&mut dyn $trait_name) -> bool + Send + Sync
361 {
362 arena.retain(|_, entity| predicate(entity));
368 }
369
370 fn pd_if_applicable<D, F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F, out: &mut [std::mem::MaybeUninit<D>])
371 where
372 D: Send,
373 F: Fn(&dyn $trait_name) -> D + Sync + Send,
374 {
375 use $crate::rayon::iter::IntoParallelRefMutIterator;
376 use $crate::rayon::iter::IndexedParallelIterator;
377 use $crate::rayon::iter::IntoParallelRefIterator;
378 use $crate::rayon::iter::ParallelIterator;
379 arena
380 .values_as_slice()
381 .par_iter()
382 .zip(out.par_iter_mut())
383 .for_each(|(e, out_slot)| {
384 *out_slot = std::mem::MaybeUninit::new(handler(e));
385 });
386 }
387
388 fn pdm_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F, out: &mut [std::mem::MaybeUninit<D>])
389 where
390 D: Send,
391 F: Fn(&mut dyn $trait_name) -> D + Sync + Send,
392 {
393 use $crate::rayon::iter::IntoParallelRefMutIterator;
394 use $crate::rayon::iter::IndexedParallelIterator;
395 use $crate::rayon::iter::ParallelIterator;
396 arena
397 .values_as_mut_slice()
398 .par_iter_mut()
399 .zip(out.par_iter_mut())
400 .for_each(|(e, out_slot)| {
401 *out_slot = std::mem::MaybeUninit::new(handler(e));
402 });
403 }
404
405 fn pda_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F, i: &[D])
406 where
407 D: Sync,
408 F: Fn(&mut dyn $trait_name, &D) + Send + Sync {
409 use $crate::rayon::iter::IntoParallelRefMutIterator;
410 use $crate::rayon::iter::IndexedParallelIterator;
411 use $crate::rayon::iter::IntoParallelRefIterator;
412 use $crate::rayon::iter::ParallelIterator;
413 arena
414 .values_as_mut_slice()
415 .par_iter_mut()
416 .zip(i.par_iter())
417 .for_each(|(e, in_value)| {
418 handler(e, in_value);
419 });
420 }
421
422 const ACTIVE: bool = true;
423}
424
425)*
426 }
427 };
428}
429
430#[macro_export]
431macro_rules! __world_define_visitors_common {
432 (@pass_entity_tuple $struct_name:ident $($trait_name:ident),* @ $entity_tuple:tt) => {
436 $crate::paste::paste! {
437 $(
438 #[allow(unused)]
440 pub fn [<visit_ $trait_name:snake>]<F>(&self, mut handler: F)
441 where
442 F: FnMut(&dyn $trait_name)
443 {
444 $crate::__world_define_visitors_common!(@v_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
445 }
446
447 #[allow(unused)]
449 pub fn [<visit_mut_ $trait_name:snake>]<F>(&mut self, mut handler: F)
450 where
451 F: FnMut(&mut dyn $trait_name)
452 {
453 $crate::__world_define_visitors_common!(@vm_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
454 }
455
456 #[allow(unused)]
462 pub fn [<visit_key_ $trait_name:snake>]<F>(&self, mut handler: F)
463 where
464 F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name)
465 {
466 $crate::__world_define_visitors_common!(@vk_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
467 }
468
469 #[allow(unused)]
475 pub fn [<visit_key_mut_ $trait_name:snake>]<F>(&mut self, mut handler: F)
476 where
477 F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name)
478 {
479 $crate::__world_define_visitors_common!(@vkm_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
480 }
481
482 #[allow(unused)]
484 pub fn [<retain_ $trait_name:snake>]<F>(&mut self, mut predicate: F)
485 where
486 F: FnMut(&mut dyn $trait_name) -> bool
487 {
488 self.[<retain_with_default_ $trait_name:snake>]::<true, F>(predicate)
489 }
490
491 #[allow(unused)]
499 pub fn [<retain_with_default_ $trait_name:snake>]<const DEFAULT: bool, F>(&mut self, mut predicate: F)
500 where
501 F: FnMut(&mut dyn $trait_name) -> bool
502 {
503 $crate::__world_define_visitors_common!(@r_use_entity_tuple $struct_name $trait_name $entity_tuple self predicate DEFAULT);
504 }
505
506 #[allow(unused)]
512 pub fn [<diff_ $trait_name:snake>]<D, F>(&mut self, mut handler: F) -> Vec<D>
513 where
514 F: FnMut(&dyn $trait_name) -> D
515 {
516 $crate::__world_define_visitors_common!(@d_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
517 }
518
519 #[allow(unused)]
525 pub fn [<diff_mut_ $trait_name:snake>]<D, F>(&mut self, mut handler: F) -> Vec<D>
526 where
527 F: FnMut(&mut dyn $trait_name) -> D
528 {
529 $crate::__world_define_visitors_common!(@dm_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
530 }
531
532 #[allow(unused)]
537 pub fn [<diff_apply_ $trait_name:snake>]<D, F>(&mut self, diff: Vec<D>, mut handler: F)
538 where F: FnMut(&mut dyn $trait_name, &D)
539 {
540 $crate::__world_define_visitors_common!(@da_use_entity_tuple $struct_name $trait_name $entity_tuple self diff handler);
541 }
542
543 #[allow(unused)]
546 pub fn [<clear_ $trait_name:snake>](&mut self) {
547 $crate::__world_define_visitors_common!(@clear_use_entity_tuple $struct_name $trait_name $entity_tuple self);
548 }
549
550 #[allow(unused)]
552 pub fn [<len_ $trait_name:snake>](&self) -> usize {
553 $crate::__world_define_visitors_common!(@len_use_entity_tuple $struct_name $trait_name $entity_tuple self)
554 }
555
556 #[allow(unused)]
558 pub fn [<any_arenas_ $trait_name:snake>](&self) -> [&dyn $crate::ErasedArena; $crate::__world_define_visitors_common!(@any_arenas_count_use_entity_tuple $struct_name $trait_name $entity_tuple)] {
559 $crate::__world_define_visitors_common!(@any_arenas_use_entity_tuple $struct_name $trait_name $entity_tuple self)
560 }
561
562 #[allow(unused)]
564 pub fn [<any_arenas_mut_ $trait_name:snake>](&mut self) -> [&mut dyn $crate::ErasedArena; $crate::__world_define_visitors_common!(@any_arenas_count_use_entity_tuple $struct_name $trait_name $entity_tuple)] {
565 $crate::__world_define_visitors_common!(@any_arenas_mut_use_entity_tuple $struct_name $trait_name $entity_tuple self)
566 }
567 )*
568 }
569 };
570
571 (@v_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
572 $crate::paste::paste! {
573 $(
574 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::v_if_applicable(
575 &$self_ident.[<$entity:snake>],
576 &mut $handler_ident,
577 );
578 )*
579 }
580 };
581
582 (@vk_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
583 $crate::paste::paste! {
584 $(
585 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::vk_if_applicable(
586 &$self_ident.[<$entity:snake>],
587 &mut $handler_ident,
588 );
589 )*
590 }
591 };
592
593 (@vm_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
594 $crate::paste::paste! {
595 $(
596 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::mv_if_applicable(
597 &mut $self_ident.[<$entity:snake>],
598 &mut $handler_ident,
599 );
600 )*
601 }
602 };
603
604 (@vkm_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
605 $crate::paste::paste! {
606 $(
607 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::vkm_if_applicable(
608 &mut $self_ident.[<$entity:snake>],
609 &mut $handler_ident,
610 );
611 )*
612 }
613 };
614
615 (@r_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $predicate:ident $default:ident) => {
616 $crate::paste::paste! {
617 $(
618 if <() as [<$struct_name VisitIf $trait_name>]<$entity>>::ACTIVE {
619 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::r_if_applicable::<_>(
620 &mut $self_ident.[<$entity:snake>],
621 &mut $predicate,
622 );
623 } else {
624 if !$default {
625 $self_ident.[<$entity:snake>].clear();
626 }
627 }
628 )*
629 }
630 };
631
632 (@d_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
633 $crate::paste::paste! {
634 let len = $self_ident.[<len_$trait_name:snake>]();
635 let mut out: Vec<std::mem::MaybeUninit<D>> = Vec::with_capacity(len);
637 unsafe { out.set_len(len); }
638 let mut offset = 0usize;
639 $(
640 let arena_len = <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
641 & $self_ident.[<$entity:snake>],
642 );
643
644 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::d_if_applicable(
645 & $self_ident.[<$entity:snake>],
646 &mut $handler_ident,
647 &mut out[offset..offset + arena_len],
648 );
649
650 offset += arena_len;
651 )*
652
653 return unsafe { let ptr = out.as_mut_ptr() as *mut D;
655 let len = out.len();
656 let cap = out.capacity();
657 ::std::mem::forget(out);
658 ::std::vec::Vec::from_raw_parts(ptr, len, cap)
659 };
660 }
661 };
662
663 (@dm_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
664 $crate::paste::paste! {
665 let len = $self_ident.[<len_$trait_name:snake>]();
666 let mut out: Vec<std::mem::MaybeUninit<D>> = Vec::with_capacity(len);
668 unsafe { out.set_len(len); }
669 let mut offset = 0usize;
670 $(
671 let arena_len = <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
672 & $self_ident.[<$entity:snake>],
673 );
674
675 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::dm_if_applicable(
676 &mut $self_ident.[<$entity:snake>],
677 &mut $handler_ident,
678 &mut out[offset..offset + arena_len],
679 );
680
681 offset += arena_len;
682 )*
683
684 return unsafe { let ptr = out.as_mut_ptr() as *mut D;
686 let len = out.len();
687 let cap = out.capacity();
688 ::std::mem::forget(out);
689 ::std::vec::Vec::from_raw_parts(ptr, len, cap)
690 };
691 }
692 };
693
694 (@da_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $diff_ident:ident $handler_ident:ident) => {
695 $crate::paste::paste! {
696 let mut offset = 0usize;
697 $(
698 let arena_len = <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
699 & $self_ident.[<$entity:snake>],
700 );
701
702 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::da_if_applicable(
703 &mut $self_ident.[<$entity:snake>],
704 &mut $handler_ident,
705 &$diff_ident[offset..offset + arena_len],
706 );
707
708 offset += arena_len;
709 )*
710 }
711 };
712
713 (@clear_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident) => {
714 $crate::paste::paste! {
715 $(
716 <() as [<$struct_name VisitIf $trait_name>]<$entity>>::clear_if_applicable(
717 &mut $self_ident.[<$entity:snake>],
718 );
719 )*
720 }
721 };
722
723 (@len_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident) => {
724 $crate::paste::paste! {
725 {
726 let mut total = 0usize;
727 $(
728 total += <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
729 & $self_ident.[<$entity:snake>],
730 );
731 )*
732 total
733 }
734 }
735 };
736
737 (@any_arenas_count_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) ) => {
738 $crate::paste::paste! {
739 {
740 0 $(+ if <() as [<$struct_name VisitIf $trait_name>]<$entity>>::ACTIVE {1} else {0})*
741 }
742 }
743 };
744
745 (@any_arenas_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident) => {
746 $crate::paste::paste! {
747 {
748 const NUM_ARENAS: usize = 0 $(+ if <() as [<$struct_name VisitIf $trait_name>]<$entity>>::ACTIVE {1} else {0})*;
749 let mut tmp: [std::mem::MaybeUninit<&dyn $crate::ErasedArena>; NUM_ARENAS] = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
750 let mut idx = 0;
751 $(
752 if <() as [<$struct_name VisitIf $trait_name>]<$entity>>::ACTIVE {
753 tmp[idx] = std::mem::MaybeUninit::new(&$self_ident.[<$entity:snake>] as &dyn $crate::ErasedArena);
754 idx += 1;
755 }
756 )*
757 unsafe {
758 std::mem::transmute::<
759 [std::mem::MaybeUninit<&dyn $crate::ErasedArena>; NUM_ARENAS],
760 [&dyn $crate::ErasedArena; NUM_ARENAS]
761 >(tmp)
762 }
763 }
764 }
765 };
766
767 (@any_arenas_mut_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident) => {
768 $crate::paste::paste! {
769 {
770 const NUM_ARENAS: usize = 0 $(+ if <() as [<$struct_name VisitIf $trait_name>]<$entity>>::ACTIVE {1} else {0})*;
771 let mut tmp: [std::mem::MaybeUninit<&mut dyn $crate::ErasedArena>; NUM_ARENAS] = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
772 let mut idx = 0;
773 $(
774 if <() as [<$struct_name VisitIf $trait_name>]<$entity>>::ACTIVE {
775 tmp[idx] = std::mem::MaybeUninit::new(&mut $self_ident.[<$entity:snake>] as &mut dyn $crate::ErasedArena);
776 idx += 1;
777 }
778 )*
779 unsafe {
780 std::mem::transmute::<
781 [std::mem::MaybeUninit<&mut dyn $crate::ErasedArena>; NUM_ARENAS],
782 [&mut dyn $crate::ErasedArena; NUM_ARENAS]
783 >(tmp)
784 }
785 }
786 }
787 };
788}
789
790#[macro_export]
791#[cfg(not(feature = "rayon"))]
792macro_rules! __world_define_visitors {
793 (@pass_entity_tuple $struct_name:ident $($trait_name:ident),* @ $entity_tuple:tt) => {
795 $crate::__world_define_visitors_common!(@pass_entity_tuple $struct_name $($trait_name),* @ $entity_tuple);
796 };
797}
798
799#[macro_export]
800#[cfg(feature = "rayon")]
801macro_rules! __world_define_visitors {
802 (@pass_entity_tuple $struct_name:ident $($trait_name:ident),* @ $entity_tuple:tt) => {
806 $crate::__world_define_visitors_common!(@pass_entity_tuple $struct_name $($trait_name),* @ $entity_tuple);
808
809 $crate::paste::paste! {
811 $(
812 #[allow(unused)]
814 pub fn [<par_visit_ $trait_name:snake>]<F>(&self, handler: F)
815 where
816 F: Fn(&dyn $trait_name) + Send + Sync
817 {
818 $crate::__world_define_visitors!(@pv_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
819 }
820
821 #[allow(unused)]
823 pub fn [<par_visit_mut_ $trait_name:snake>]<F>(&mut self, handler: F)
824 where
825 F: Fn(&mut dyn $trait_name) + Send + Sync
826 {
827 $crate::__world_define_visitors!(@pvm_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
828 }
829
830 #[allow(unused)]
837 pub fn [<par_visit_key_ $trait_name:snake>]<F>(&self, handler: F)
838 where
839 F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name) + Send + Sync
840 {
841 $crate::__world_define_visitors!(@pvk_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
842 }
843
844 #[allow(unused)]
851 pub fn [<par_visit_key_mut_ $trait_name:snake>]<F>(&mut self, handler: F)
852 where
853 F: Fn(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name) + Send + Sync
854 {
855 $crate::__world_define_visitors!(@pvkm_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
856 }
857
858 #[allow(unused)]
860 pub fn [<par_retain_ $trait_name:snake>]<F>(&mut self, mut predicate: F)
861 where
862 F: Fn(&mut dyn $trait_name) -> bool + Send + Sync
863 {
864 self.[<par_retain_with_default_ $trait_name:snake>]::<true, F>(predicate)
865 }
866
867 #[allow(unused)]
878 pub fn [<par_retain_with_default_ $trait_name:snake>]<const DEFAULT: bool, F>(&mut self, mut predicate: F)
879 where
880 F: Fn(&mut dyn $trait_name) -> bool + Send + Sync
881 {
882 $crate::__world_define_visitors!(@pr_use_entity_tuple $struct_name $trait_name $entity_tuple self predicate DEFAULT);
883 }
884
885 #[allow(unused)]
890 pub fn [<par_diff_ $trait_name:snake>]<D, F>(&mut self, mut handler: F) -> Vec<D>
891 where
892 D: Send,
893 F: Fn(&dyn $trait_name) -> D + Send + Sync
894 {
895 $crate::__world_define_visitors!(@pd_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
896 }
897
898 #[allow(unused)]
904 pub fn [<par_diff_mut_ $trait_name:snake>]<D, F>(&mut self, mut handler: F) -> Vec<D>
905 where
906 D: Send,
907 F: Fn(&mut dyn $trait_name) -> D + Send + Sync
908 {
909 $crate::__world_define_visitors!(@pdm_use_entity_tuple $struct_name $trait_name $entity_tuple self handler);
910 }
911
912 #[allow(unused)]
917 pub fn [<par_diff_apply_ $trait_name:snake>]<D, F>(&mut self, diff: Vec<D>, handler: F)
918 where
919 D: Sync,
920 F: Fn(&mut dyn $trait_name, &D) + Send + Sync
921 {
922 $crate::__world_define_visitors!(@pda_use_entity_tuple $struct_name $trait_name $entity_tuple self diff handler);
923 }
924 )*
925 }
926 };
927
928 (@pv_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
929 $crate::paste::paste! {
930 use $crate::rayon::scope;
931 scope(|s| {
932 $(
933 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
934 let arena_ref = &$self_ident.[<$entity:snake>];
935 s.spawn(|_| {
936 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pv_if_applicable(
937 arena_ref,
938 &$handler_ident,
939 );
940 });
941 }
942 )*
943 });
944 }
945 };
946
947 (@pvk_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
948 $crate::paste::paste! {
949 use $crate::rayon::scope;
950 scope(|s| {
951 $(
952 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
953 let arena_ref = &$self_ident.[<$entity:snake>];
954 s.spawn(|_| {
955 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pvk_if_applicable(
956 arena_ref,
957 &$handler_ident,
958 );
959 });
960 }
961 )*
962 });
963 }
964 };
965
966 (@pvm_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
967 $crate::paste::paste! {
968 use $crate::rayon::scope;
969 scope(|s| {
970 $(
971 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
972 s.spawn(|_| {
973 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pvm_if_applicable(
974 &mut $self_ident.[<$entity:snake>],
975 &$handler_ident,
976 );
977 });
978 }
979 )*
980 });
981 }
982 };
983
984 (@pvkm_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
985 $crate::paste::paste! {
986 use $crate::rayon::scope;
987 scope(|s| {
988 $(
989 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
990 s.spawn(|_| {
991 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pvkm_if_applicable(
992 &mut $self_ident.[<$entity:snake>],
993 &$handler_ident,
994 );
995 });
996 }
997 )*
998 });
999 }
1000 };
1001
1002 (@pr_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $predicate_ident:ident $default:ident) => {
1003 $crate::paste::paste! {
1004 use $crate::rayon::scope;
1005 scope(|s| {
1006 $(
1007 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
1008 s.spawn(|_| {
1009 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pr_if_applicable::<_>(
1010 &mut $self_ident.[<$entity:snake>],
1011 &$predicate_ident,
1012 );
1013 });
1014 } else {
1015 if !$default {
1016 $self_ident.[<$entity:snake>].clear();
1017 }
1018 }
1019 )*
1020 });
1021 }
1022 };
1023
1024 (@pd_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
1025 $crate::paste::paste! {
1026 let len = $self_ident.[<len_$trait_name:snake>]();
1027 let mut out: Vec<std::mem::MaybeUninit<D>> = Vec::with_capacity(len);
1029 unsafe { out.set_len(len); }
1030 use $crate::rayon::scope;
1031 scope(|s| {
1032 let mut remaining: &mut [_] = &mut out[..];
1033 $(
1034 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
1035 let arena_len = <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
1036 & $self_ident.[<$entity:snake>],
1037 );
1038
1039 let (arena_slice, rest) = remaining.split_at_mut(arena_len);
1040 remaining = rest;
1041 let arena_ref = &$self_ident.[<$entity:snake>];
1042 let handler_ref = &$handler_ident;
1043 s.spawn(move |_| {
1044 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pd_if_applicable(
1045 arena_ref,
1046 handler_ref,
1047 arena_slice,
1048 );
1049 });
1050 }
1051 )*
1052 });
1053
1054 return unsafe { let ptr = out.as_mut_ptr() as *mut D;
1056 let len = out.len();
1057 let cap = out.capacity();
1058 ::std::mem::forget(out);
1059 ::std::vec::Vec::from_raw_parts(ptr, len, cap)
1060 };
1061 }
1062 };
1063
1064 (@pdm_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
1065 $crate::paste::paste! {
1066 let len = $self_ident.[<len_$trait_name:snake>]();
1067 let mut out: Vec<std::mem::MaybeUninit<D>> = Vec::with_capacity(len);
1069 unsafe { out.set_len(len); }
1070 use $crate::rayon::scope;
1071 scope(|s| {
1072 let mut remaining: &mut [_] = &mut out[..];
1073 $(
1074 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
1075 let arena_len = <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
1076 & $self_ident.[<$entity:snake>],
1077 );
1078
1079 let (arena_slice, rest) = remaining.split_at_mut(arena_len);
1080 remaining = rest;
1081 let arena_ref = &mut $self_ident.[<$entity:snake>];
1082 let handler_ref = &$handler_ident;
1083 s.spawn(move |_| {
1084 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pdm_if_applicable(
1085 arena_ref,
1086 handler_ref,
1087 arena_slice,
1088 );
1089 });
1090 }
1091 )*
1092 });
1093
1094 return unsafe { let ptr = out.as_mut_ptr() as *mut D;
1096 let len = out.len();
1097 let cap = out.capacity();
1098 ::std::mem::forget(out);
1099 ::std::vec::Vec::from_raw_parts(ptr, len, cap)
1100 };
1101 }
1102 };
1103
1104 (@pda_use_entity_tuple $struct_name:ident $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $diff_ident:ident $handler_ident:ident) => {
1105 $crate::paste::paste! {
1106 use $crate::rayon::scope;
1107 scope(|s| {
1108 let mut remaining: &[_] = &$diff_ident[..];
1109 $(
1110 if <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::ACTIVE {
1111 let arena_len = <() as [<$struct_name VisitIf $trait_name>]<$entity>>::len_if_applicable(
1112 & $self_ident.[<$entity:snake>],
1113 );
1114
1115 let (arena_slice, rest) = remaining.split_at(arena_len);
1116 remaining = rest;
1117 let arena_ref = &mut $self_ident.[<$entity:snake>];
1118 let handler_ref = &$handler_ident;
1119
1120 s.spawn(move |_| {
1121 <() as [<$struct_name ParVisitIf $trait_name>]<$entity>>::pda_if_applicable(
1122 arena_ref,
1123 handler_ref,
1124 arena_slice,
1125 );
1126 });
1127 }
1128 )*
1129 });
1130 }
1131};
1132}
1133
1134#[macro_export]
1135#[cfg(not(feature = "debug"))]
1136macro_rules! __world_define_struct {
1137 ($struct_name:ident, $( $entity:ty ),*) => {
1138 $crate::paste::paste! {
1139 #[derive(Default)]
1140 #[allow(private_interfaces)] pub struct $struct_name {
1142 $(
1143 pub [<$entity:snake>]: $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity>,
1144 )*
1145 }
1146 }
1147 };
1148}
1149
1150#[macro_export]
1151#[cfg(feature = "debug")]
1152macro_rules! __world_define_struct {
1153 ($struct_name:ident, $( $entity:ty ),*) => {
1154 $crate::paste::paste! {
1155 #[derive(Default, Debug)]
1156 #[allow(private_interfaces)] pub struct $struct_name {
1158 $(
1159 pub [<$entity:snake>]: $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity>,
1160 )*
1161 }
1162 }
1163 };
1164}
1165
1166#[macro_export]
1167#[cfg(not(feature = "serde"))]
1168macro_rules! __world_serde_support {
1169 ($struct_name:ident $( $entity:ty ),*) => {};
1170}
1171
1172#[macro_export]
1173#[cfg(feature = "serde")]
1174macro_rules! __world_serde_support {
1175 ($struct_name:ident $( $entity:ty ),*) => {
1176 $crate::paste::paste! {
1177
1178impl $crate::serde::Serialize for [<$struct_name ArenaID>] {
1179 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1180 where
1181 S: $crate::serde::Serializer,
1182 {
1183 let s = match self.0 {
1184 $(
1185 i if i == $struct_name::arena_id::<$entity>().0 => stringify!($entity),
1186 )*
1187 _ => return Err($crate::serde::ser::Error::custom(format!("Unknown ArenaID {}", self.0))),
1189 };
1190 serializer.serialize_str(s)
1191 }
1192}
1193
1194impl<'de> $crate::serde::Deserialize<'de> for [<$struct_name ArenaID>] {
1195 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1196 where
1197 D: $crate::serde::Deserializer<'de>,
1198 {
1199 let s = String::deserialize(deserializer)?;
1200 let id = match s.as_str() {
1201 $(
1202 stringify!($entity) => $struct_name::arena_id::<$entity>().0,
1203 )*
1204 _ => return Err($crate::serde::de::Error::custom(format!("Unknown ArenaID string {}", s))),
1206 };
1207 Ok([<$struct_name ArenaID>](id))
1208 }
1209}
1210
1211impl $crate::serde::ser::Serialize for $struct_name {
1212 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1213 where
1214 S: $crate::serde::ser::Serializer,
1215 {
1216 use $crate::SerdeArena;
1217 use $crate::serde::ser::SerializeStruct;
1218
1219 let field_count = 0 $( + if <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'static>>::ACTIVE { 1 } else { 0 } )*;
1220 let mut state = serializer.serialize_struct(
1221 stringify!($struct_name),
1222 field_count
1223 )?;
1224 $(
1225 self.[<$entity:snake>].serialize_arena(stringify!($entity), &mut state)?;
1226 )*
1227 state.end()
1228 }
1229}
1230
1231static [<$struct_name:upper _DESERIALIZE_FIELDS>]: &'static [&'static str] = &{
1233 const TMP: [Option<&'static str>; { 0 $(+ { let _ = stringify!($entity); 1 })* }] = [
1234 $(
1235 if <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity>
1236 as $crate::SerdeArena<'static>>::ACTIVE {
1237 Some(stringify!($entity))
1238 } else {
1239 None
1240 }
1241 ),*
1242 ];
1243
1244 const COUNT: usize = 0 $(+ if (<$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity>
1245 as $crate::SerdeArena<'static>>::ACTIVE) {1} else {0})*;
1246
1247 let mut arr: [&'static str; COUNT] = [""; COUNT];
1248 let mut j = 0;
1249 let mut k = 0;
1250 while j < TMP.len() {
1251 if let Some(s) = TMP[j] {
1252 arr[k] = s;
1253 k += 1;
1254 }
1255 j += 1;
1256 }
1257
1258 arr
1259};
1260
1261impl<'de> $crate::serde::Deserialize<'de> for $struct_name {
1262 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1263 where
1264 D: $crate::serde::Deserializer<'de>,
1265 {
1266 use $crate::serde::de::{MapAccess, SeqAccess, Visitor, Error};
1267 use std::fmt;
1268
1269 struct WorldVisitor;
1270
1271 impl<'de> Visitor<'de> for WorldVisitor {
1272 type Value = $struct_name;
1273
1274 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
1275 write!(f, "struct {}", stringify!($struct_name))
1276 }
1277
1278 fn visit_map<V>(self, mut map: V) -> Result<$struct_name, V::Error>
1280 where
1281 V: MapAccess<'de>,
1282 {
1283 let mut world = $struct_name::default();
1284
1285 while let Some(key) = map.next_key::<String>()? {
1286 match key.as_str() {
1287 $(
1288 stringify!($entity) => {
1289 world.[<$entity:snake>] =
1290 <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'de>>::deserialize_arena(&mut map)?;
1291 }
1292 )*
1293 other => {
1294 return Err(V::Error::custom(format!(
1295 "Unknown field '{}' for {}",
1296 other,
1297 stringify!($struct_name)
1298 )));
1299 }
1300 }
1301 }
1302
1303 Ok(world)
1304 }
1305
1306 fn visit_seq<V>(self, mut seq: V) -> Result<$struct_name, V::Error>
1309 where
1310 V: SeqAccess<'de>,
1311 {
1312 Ok($struct_name {
1313 $(
1314 [<$entity:snake>]: <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'de>>::from_seq(&mut seq, stringify!($entity))?,
1315 )*
1316 })
1317 }
1318 }
1319
1320 deserializer.deserialize_struct(
1325 stringify!($struct_name),
1326 &[<$struct_name:upper _DESERIALIZE_FIELDS>],
1327 WorldVisitor,
1328 )
1329 }
1330}
1331 }
1332 };
1333}
1334
1335#[macro_export]
1336macro_rules! world {
1337 (
1339 $struct_name:ident, $( $entity:ty ),* $(,)? ;$( $trait_name:ident ),* $(,)? ) => {
1346 $crate::paste::paste! {
1347
1348#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1353pub struct [<$struct_name ArenaID>](usize);
1354
1355$crate::__world_define_struct!($struct_name, $($entity),*);
1356
1357$(
1358 trait [<$struct_name VisitIf $trait_name>]<T> {
1359 fn v_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F)
1360 where
1361 F: FnMut(&dyn $trait_name);
1362
1363 fn mv_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F)
1364 where
1365 F: FnMut(&mut dyn $trait_name);
1366
1367 fn vk_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F)
1368 where
1369 F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name);
1370
1371 fn vkm_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F)
1372 where
1373 F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name);
1374
1375 fn r_if_applicable<P>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, predicate: P)
1376 where
1377 P: FnMut(&mut dyn $trait_name) -> bool;
1378
1379 fn d_if_applicable<D, F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F, out: &mut [std::mem::MaybeUninit<D>])
1380 where
1381 F: FnMut(&dyn $trait_name) -> D;
1382
1383 fn dm_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F, out: &mut [std::mem::MaybeUninit<D>])
1384 where
1385 F: FnMut(&mut dyn $trait_name) -> D;
1386
1387 fn da_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F, i: &[D])
1388 where
1389 F: FnMut(&mut dyn $trait_name, &D);
1390
1391 fn clear_if_applicable(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>);
1392
1393 fn len_if_applicable(arena: & $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>) -> usize;
1394
1395 const ACTIVE: bool;
1396 }
1397
1398 impl<T> [<$struct_name VisitIf $trait_name>]<T> for () {
1400 default fn v_if_applicable<F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F)
1401 where F: FnMut(&dyn $trait_name) {}
1402
1403 default fn mv_if_applicable<F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F)
1404 where F: FnMut(&mut dyn $trait_name) {}
1405
1406 default fn vk_if_applicable<F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F)
1407 where F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name) {}
1408
1409 default fn vkm_if_applicable<F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F)
1410 where F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name) {}
1411
1412 default fn r_if_applicable<P>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _predicate: P)
1413 where P: FnMut(&mut dyn $trait_name) -> bool {}
1414
1415 default fn d_if_applicable<D, F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F, _out: &mut [std::mem::MaybeUninit<D>])
1416 where
1417 F: FnMut(&dyn $trait_name) -> D {}
1418
1419 default fn dm_if_applicable<D, F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F, _out: &mut [std::mem::MaybeUninit<D>])
1420 where
1421 F: FnMut(&mut dyn $trait_name) -> D {}
1422
1423 default fn da_if_applicable<D, F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F, _i: &[D])
1424 where
1425 F: FnMut(&mut dyn $trait_name, &D) {}
1426
1427 default fn clear_if_applicable(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>) {}
1428
1429 default fn len_if_applicable(_arena: & $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>) -> usize { 0 }
1430
1431 default const ACTIVE: bool = false;
1432 }
1433
1434 impl<T: $trait_name> [<$struct_name VisitIf $trait_name>]<T> for () {
1435 fn v_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F)
1436 where F: FnMut(&dyn $trait_name)
1437 {
1438 arena
1439 .values_as_slice()
1440 .iter()
1441 .for_each(|entity| handler(entity));
1442 }
1443
1444 fn mv_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F)
1445 where F: FnMut(&mut dyn $trait_name)
1446 {
1447 arena
1448 .values_as_mut_slice()
1449 .iter_mut()
1450 .for_each(|entity| handler(entity));
1451 }
1452
1453 fn r_if_applicable<P>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut predicate: P)
1454 where P: FnMut(&mut dyn $trait_name) -> bool
1455 {
1456 arena.retain(|_, entity| predicate(entity));
1457 }
1458
1459 fn d_if_applicable<D, F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F, out: &mut [std::mem::MaybeUninit<D>])
1460 where
1461 F: FnMut(&dyn $trait_name) -> D {
1462 for (e, out_slot) in arena.values_as_slice().iter().zip(out.iter_mut()) {
1463 *out_slot = std::mem::MaybeUninit::new(handler(e));
1464 }
1465 }
1466
1467 fn dm_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F, out: &mut [std::mem::MaybeUninit<D>])
1468 where
1469 F: FnMut(&mut dyn $trait_name) -> D {
1470 for (e, out_slot) in arena.values_as_mut_slice().iter_mut().zip(out.iter_mut()) {
1471 *out_slot = std::mem::MaybeUninit::new(handler(e));
1472 }
1473 }
1474
1475 fn da_if_applicable<D, F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F, i: &[D])
1476 where
1477 F: FnMut(&mut dyn $trait_name, &D) {
1478 for (e, in_value) in arena.values_as_mut_slice().iter_mut().zip(i.iter()) {
1479 handler(e, in_value);
1480 }
1481 }
1482
1483 fn vk_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F)
1484 where F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &dyn $trait_name)
1485 {
1486 let keys = arena.keys_as_slice();
1487 let values = arena.values_as_slice();
1488 keys.iter()
1489 .zip(values.iter())
1490 .for_each(|(k, v)| handler(($struct_name::arena_id::<T>(), *k), v));
1491 }
1492
1493 fn vkm_if_applicable<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F)
1494 where F: FnMut(([<$struct_name ArenaID>], $crate::slotmap::DefaultKey), &mut dyn $trait_name)
1495 {
1496 let (keys, values) = arena.keys_values_as_mut_slices();
1497 keys.iter()
1498 .zip(values.iter_mut())
1499 .for_each(|(k, v)| handler(($struct_name::arena_id::<T>(), *k), v));
1500 }
1501
1502 fn clear_if_applicable(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>) {
1503 arena.clear();
1504 }
1505
1506 fn len_if_applicable(arena: & $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>) -> usize {
1507 arena.len()
1508 }
1509
1510 default const ACTIVE: bool = true;
1511 }
1512
1513)*
1514
1515impl $struct_name {
1516 $crate::__world_define_visitors!(@pass_entity_tuple $struct_name $($trait_name),* @ ($($entity),*));
1517
1518 #[allow(unused)]
1523 pub fn arena<T>(&self) -> &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T> {
1524 use $crate::ArenaCast;
1525 $(
1526 if <T as $crate::IsType<$entity>>::VALUE {
1527 return <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as ArenaCast<T>>::cast(&self.[<$entity:snake>]);
1528 }
1529 )* panic!("In call to {}::arena::<{}>(), {} not registered", stringify!($struct_name), std::any::type_name::<T>(), std::any::type_name::<T>());
1531 }
1532
1533 #[allow(unused)]
1538 pub fn arena_mut<T>(&mut self) -> &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T> {
1539 use $crate::ArenaCast;
1540 $(
1541 if <T as $crate::IsType<$entity>>::VALUE {
1542 return <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as ArenaCast<T>>::cast_mut(&mut self.[<$entity:snake>]);
1543 }
1544 )*
1545 panic!("In call to {}::arena_mut::<{}>(), {} not registered", stringify!($struct_name), std::any::type_name::<T>(), std::any::type_name::<T>());
1546 }
1547
1548 #[allow(unused)]
1556 pub fn arena_id<T>() -> [<$struct_name ArenaID>] {
1557 let mut i = 0usize;
1558 $(
1559 if <T as $crate::IsType<$entity>>::VALUE {
1560 return [<$struct_name ArenaID>](i);
1561 }
1562 i += 1;
1563 )*
1564 panic!("In call to {}::arena_id::<{}>(), {} not registered", stringify!($struct_name), std::any::type_name::<T>(), std::any::type_name::<T>());
1565 }
1566
1567 #[allow(unused)]
1569 pub fn any_arena(&self, which: [<$struct_name ArenaID>]) -> &dyn $crate::ErasedArena {
1570 match which.0 {
1571 $(
1572 i if i == Self::arena_id::<$entity>().0 => &self.[<$entity:snake>] as &dyn $crate::ErasedArena,
1573 )*
1574 _ => panic!("No arena for type id {}", which.0),
1575 }
1576 }
1577
1578 #[allow(unused)]
1580 pub fn any_arena_mut(&mut self, which: [<$struct_name ArenaID>]) -> &mut dyn $crate::ErasedArena {
1581 match which.0 {
1582 $(
1583 i if i == Self::arena_id::<$entity>().0 => &mut self.[<$entity:snake>] as &mut dyn $crate::ErasedArena,
1584 )*
1585 _ => panic!("No mutable arena for type id {}", which.0),
1586 }
1587 }
1588
1589 #[allow(unused)]
1590 pub fn clear(&mut self) {
1591 $(
1592 self.[<$entity:snake>].clear();
1593 )*
1594 }
1595
1596 #[allow(unused)]
1597 pub fn len(&self) -> usize {
1598 0 $( + self.[<$entity:snake>].len() )*
1599 }
1600}
1601
1602$crate::__world_serde_support!($struct_name $($entity),*);
1603
1604$crate::__world_define_rayon_trait_helpers!($struct_name $($trait_name),*);
1605
1606 }
1607 };
1608}
1609
1610#[cfg(test)]
1614mod tests {
1615 #[derive(Debug)]
1617 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1618 struct Player {
1619 id: i32,
1620 }
1621
1622 #[derive(Debug)]
1623 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1624 struct Enemy {
1625 hp: i32,
1626 }
1627
1628 #[derive(Debug)]
1630 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1631 struct NonTrait {
1632 #[allow(unused)]
1633 val: i32,
1634 }
1635
1636 pub trait TestTrait {
1637 fn metric(&self) -> i32;
1638 fn add(&mut self, delta: i32);
1639 }
1640 impl TestTrait for Player {
1641 fn metric(&self) -> i32 {
1642 self.id
1643 }
1644 fn add(&mut self, delta: i32) {
1645 self.id += delta;
1646 }
1647 }
1648 impl TestTrait for Enemy {
1649 fn metric(&self) -> i32 {
1650 self.hp
1651 }
1652 fn add(&mut self, delta: i32) {
1653 self.hp += delta;
1654 }
1655 }
1656
1657 pub trait SecondTestTrait {
1659 fn touch(&mut self);
1660 }
1661 impl SecondTestTrait for Player {
1662 fn touch(&mut self) {
1663 self.id += 1000;
1664 }
1665 }
1666
1667 world!(MyWorld, Enemy, Player; TestTrait, SecondTestTrait);
1669
1670 world!(AnotherWorld, Enemy, NonTrait, Player; TestTrait, SecondTestTrait);
1672
1673 #[test]
1676 fn basic_arena_access_and_len() {
1677 let mut world = MyWorld::default();
1678
1679 let p0 = world.player.insert(Player { id: 1 });
1680 let e0 = world.arena_mut::<Enemy>().insert(Enemy { hp: 10 });
1681 let _e1 = world.arena_mut::<Enemy>().insert(Enemy { hp: 9 });
1682
1683 assert_eq!(world.len(), 3);
1684
1685 assert_eq!(world.arena::<Enemy>().len(), 2);
1687 assert_eq!(world.arena::<Player>().len(), 1);
1688
1689 assert_eq!(MyWorld::arena_id::<Enemy>().0, 0);
1691 assert_eq!(MyWorld::arena_id::<Player>().0, 1);
1692
1693 let player_id = MyWorld::arena_id::<Player>();
1695 let enemy_id = MyWorld::arena_id::<Enemy>();
1696
1697 let p = world
1698 .any_arena(player_id)
1699 .get(p0)
1700 .unwrap()
1701 .downcast_ref::<Player>()
1702 .unwrap();
1703 assert_eq!(p.id, 1);
1704
1705 let e = world
1706 .any_arena(enemy_id)
1707 .get(e0)
1708 .unwrap()
1709 .downcast_ref::<Enemy>()
1710 .unwrap();
1711 assert_eq!(e.hp, 10);
1712
1713 {
1715 let p_mut = world
1716 .any_arena_mut(player_id)
1717 .get_mut(p0)
1718 .unwrap()
1719 .downcast_mut::<Player>()
1720 .unwrap();
1721 p_mut.id += 5;
1722 }
1723 assert_eq!(world.player.get(p0).unwrap().id, 6);
1724
1725 unsafe {
1727 let p_un = world
1728 .any_arena(player_id)
1729 .get_unchecked(p0)
1730 .downcast_ref::<Player>()
1731 .unwrap();
1732 assert_eq!(p_un.id, 6);
1733 let e_unm = world
1734 .any_arena_mut(enemy_id)
1735 .get_unchecked_mut(e0)
1736 .downcast_mut::<Enemy>()
1737 .unwrap();
1738 e_unm.hp += 1;
1739 }
1740 assert_eq!(world.enemy.get(e0).unwrap().hp, 11);
1741
1742 world.clear();
1744 assert_eq!(world.len(), 0);
1745 }
1746
1747 #[test]
1748 fn visitors_immutable_mutable_and_lengths() {
1749 let mut world = MyWorld::default();
1750 world.player.insert(Player { id: 1 });
1751 world.player.insert(Player { id: 2 });
1752 world.enemy.insert(Enemy { hp: 10 });
1753 world.enemy.insert(Enemy { hp: 5 });
1754
1755 assert_eq!(world.len_test_trait(), 4);
1757
1758 let mut metrics = Vec::new();
1760 world.visit_test_trait(|t| metrics.push(t.metric()));
1761 metrics.sort();
1762 assert_eq!(metrics, vec![1, 2, 5, 10]);
1763
1764 world.visit_mut_second_test_trait(|t| t.touch());
1766 let ids: Vec<i32> = world.player.values().map(|p| p.id).collect();
1767 assert_eq!(ids, vec![1001, 1002]);
1768 let hps: Vec<i32> = world.enemy.values().map(|e| e.hp).collect();
1770 assert_eq!(hps, vec![10, 5]);
1771
1772 world.clear_test_trait();
1774 assert_eq!(world.len_test_trait(), 0);
1775 assert_eq!(world.len(), 0);
1777 }
1778
1779 #[test]
1780 fn retain_with_default_and_selective_clear() {
1781 let mut world = AnotherWorld::default();
1782
1783 let _ = world.enemy.insert(Enemy { hp: 10 });
1785 let _ = world.enemy.insert(Enemy { hp: 3 });
1786 let _ = world.non_trait.insert(NonTrait { val: 99 });
1787 let _ = world.player.insert(Player { id: 1 });
1788
1789 world.retain_with_default_test_trait::<false, _>(|t| t.metric() >= 5);
1792
1793 assert_eq!(world.enemy.len(), 1); assert_eq!(world.player.len(), 0);
1795 assert_eq!(world.non_trait.len(), 0);
1796
1797 let _ = world.player.insert(Player { id: 7 });
1799 let _ = world.non_trait.insert(NonTrait { val: 42 });
1800 world.retain_with_default_test_trait::<true, _>(|t| t.metric() >= 5);
1801
1802 assert_eq!(world.enemy.len(), 1); assert_eq!(world.player.len(), 1); assert_eq!(world.non_trait.len(), 1); world.clear_test_trait();
1808 assert_eq!(world.enemy.len(), 0);
1809 assert_eq!(world.player.len(), 0);
1810 assert_eq!(world.non_trait.len(), 1);
1811 }
1812
1813 #[test]
1814 fn diff_and_apply_roundtrip() {
1815 let mut world = MyWorld::default();
1816 world.player.insert(Player { id: 1 });
1817 world.enemy.insert(Enemy { hp: 2 });
1818 world.enemy.insert(Enemy { hp: 3 });
1819
1820 let diff = world.diff_test_trait(|t| t.metric() * 2);
1822
1823 world.diff_apply_test_trait(diff, |t, d| t.add(-d / 2));
1825
1826 let mut all_zero = true;
1828 world.visit_test_trait(|t| {
1829 all_zero = all_zero && t.metric() == 0;
1830 });
1831 assert!(all_zero);
1832 }
1833
1834 #[cfg(feature = "rayon")]
1835 #[test]
1836 fn parallel_visitors_and_diff_apply() {
1837 use std::sync::atomic::{AtomicI64, Ordering};
1838 use std::sync::{Arc, Mutex};
1839
1840 let mut world = MyWorld::default();
1841 world.player.insert(Player { id: 1 });
1842 world.player.insert(Player { id: 2 });
1843 world.enemy.insert(Enemy { hp: 10 });
1844 world.enemy.insert(Enemy { hp: 5 });
1845
1846 let sum = AtomicI64::new(0);
1848 world.par_visit_test_trait(|t| {
1849 sum.fetch_add(t.metric() as i64, Ordering::Relaxed);
1850 });
1851 assert_eq!(sum.load(Ordering::Relaxed), 1 + 2 + 10 + 5);
1852
1853 world.par_visit_mut_second_test_trait(|t| t.touch());
1855 let ids: Vec<i32> = world.player.values().map(|p| p.id).collect();
1856 assert_eq!(ids, vec![1001, 1002]);
1857
1858 let diff = world.par_diff_test_trait(|t| t.metric() * 3);
1860 world.par_diff_apply_test_trait(diff, |t, d| t.add(-d / 3));
1862
1863 let results = Arc::new(Mutex::new(Vec::new()));
1865 world.par_visit_test_trait(|t| results.lock().unwrap().push(t.metric()));
1866 let mut vals = results.lock().unwrap().clone();
1867 vals.sort();
1868 assert_eq!(vals, vec![0, 0, 0, 0]);
1869
1870 world.par_retain_with_default_test_trait::<true, _>(|t| t.metric() == 0);
1872 assert_eq!(world.len_test_trait(), 4);
1873 }
1874
1875 #[cfg(all(feature = "serde"))]
1876 #[test]
1877 fn serde_roundtrips_json_and_bincode() {
1878 let mut world = MyWorld::default();
1880 world.player.insert(Player { id: 7 });
1881 world.enemy.insert(Enemy { hp: 42 });
1882
1883 let serialized = serde_json::to_string(&world).unwrap();
1885 let de_json: MyWorld = serde_json::from_str(&serialized).unwrap();
1886 assert_eq!(de_json.player.len(), 1);
1888 assert_eq!(de_json.enemy.len(), 1);
1889 assert_eq!(de_json.player.values().next().unwrap().id, 7);
1890 assert_eq!(de_json.enemy.values().next().unwrap().hp, 42);
1891
1892 let serialized: Vec<u8> =
1894 bincode::serde::encode_to_vec(&world, bincode::config::standard()).unwrap();
1895 let (de_bin, _): (MyWorld, usize) =
1896 bincode::serde::decode_from_slice(&serialized, bincode::config::standard()).unwrap();
1897
1898 assert_eq!(de_bin.player.len(), 1);
1899 assert_eq!(de_bin.enemy.len(), 1);
1900 assert_eq!(de_bin.player.values().next().unwrap().id, 7);
1901 assert_eq!(de_bin.enemy.values().next().unwrap().hp, 42);
1902 }
1903
1904 #[test]
1905 fn empty_world_behavior() {
1906 let mut world = MyWorld::default();
1907
1908 assert_eq!(world.len(), 0);
1910 assert_eq!(world.len_test_trait(), 0);
1911 assert_eq!(world.len_second_test_trait(), 0);
1912
1913 let mut visited = false;
1915 world.visit_test_trait(|_| visited = true);
1916 assert!(!visited);
1917
1918 let diff = world.diff_test_trait(|t| t.metric());
1920 assert_eq!(diff.len(), 0);
1921 }
1922
1923 #[test]
1924 fn retain_removes_all_when_predicate_always_false() {
1925 let mut world = MyWorld::default();
1926 world.player.insert(Player { id: 1 });
1927 world.player.insert(Player { id: 2 });
1928 world.enemy.insert(Enemy { hp: 10 });
1929
1930 world.retain_test_trait(|_| false);
1932
1933 assert_eq!(world.len_test_trait(), 0);
1934 assert_eq!(world.len(), 0);
1935 }
1936
1937 #[test]
1938 fn retain_keeps_all_when_predicate_always_true() {
1939 let mut world = MyWorld::default();
1940 world.player.insert(Player { id: 1 });
1941 world.player.insert(Player { id: 2 });
1942 world.enemy.insert(Enemy { hp: 10 });
1943
1944 let initial_len = world.len_test_trait();
1945
1946 world.retain_test_trait(|_| true);
1948
1949 assert_eq!(world.len_test_trait(), initial_len);
1950 }
1951
1952 #[test]
1953 fn diff_apply_maintains_element_order() {
1954 let mut world = MyWorld::default();
1955
1956 let _e1 = world.enemy.insert(Enemy { hp: 10 });
1958 let _e2 = world.enemy.insert(Enemy { hp: 20 });
1959 let _p1 = world.player.insert(Player { id: 5 });
1960
1961 let original = world.diff_test_trait(|t| t.metric());
1963
1964 world.visit_mut_test_trait(|t| t.add(100));
1966
1967 let current = world.diff_test_trait(|t| t.metric());
1969 let restore_diff: Vec<i32> = original
1970 .iter()
1971 .zip(current.iter())
1972 .map(|(orig, curr)| orig - curr)
1973 .collect();
1974 world.diff_apply_test_trait(restore_diff, |t, delta| t.add(*delta));
1975
1976 let mut final_metrics = Vec::new();
1978 world.visit_test_trait(|t| final_metrics.push(t.metric()));
1979 assert_eq!(final_metrics, vec![10, 20, 5]);
1980 }
1981
1982 #[test]
1983 fn visit_key_provides_correct_keys_and_arena_ids() {
1984 let mut world = MyWorld::default();
1985
1986 let e1 = world.enemy.insert(Enemy { hp: 10 });
1987 let e2 = world.enemy.insert(Enemy { hp: 20 });
1988 let p1 = world.player.insert(Player { id: 5 });
1989
1990 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
1991 let player_arena_id = MyWorld::arena_id::<Player>();
1992
1993 let mut collected = Vec::new();
1995 world.visit_key_test_trait(|(arena_id, key), _entity| {
1996 collected.push((arena_id, key));
1997 });
1998
1999 assert_eq!(collected.len(), 3);
2001
2002 assert!(collected.contains(&(enemy_arena_id, e1)));
2004 assert!(collected.contains(&(enemy_arena_id, e2)));
2005 assert!(collected.contains(&(player_arena_id, p1)));
2006 }
2007
2008 #[test]
2009 fn visit_key_entity_association_with_arena_id() {
2010 let mut world = MyWorld::default();
2011
2012 let e1 = world.enemy.insert(Enemy { hp: 100 });
2013 let e2 = world.enemy.insert(Enemy { hp: 200 });
2014 let p1 = world.player.insert(Player { id: 50 });
2015
2016 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2017 let player_arena_id = MyWorld::arena_id::<Player>();
2018
2019 world.visit_key_test_trait(|(arena_id, key), entity| {
2021 let metric = entity.metric();
2022
2023 if arena_id == enemy_arena_id && key == e1 {
2025 assert_eq!(metric, 100);
2026 } else if arena_id == enemy_arena_id && key == e2 {
2027 assert_eq!(metric, 200);
2028 } else if arena_id == player_arena_id && key == p1 {
2029 assert_eq!(metric, 50);
2030 } else {
2031 panic!("Unexpected ArenaID/key combination");
2032 }
2033 });
2034 }
2035
2036 #[test]
2037 fn visit_key_mut_can_modify_entities_by_arena_id() {
2038 let mut world = MyWorld::default();
2039
2040 let e1 = world.enemy.insert(Enemy { hp: 10 });
2041 let p1 = world.player.insert(Player { id: 5 });
2042 let p2 = world.player.insert(Player { id: 7 });
2043
2044 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2045 let player_arena_id = MyWorld::arena_id::<Player>();
2046
2047 world.visit_key_mut_test_trait(|(arena_id, key), entity| {
2049 if arena_id == enemy_arena_id && key == e1 {
2050 entity.add(90); } else if arena_id == player_arena_id && key == p1 {
2052 entity.add(95); } else if arena_id == player_arena_id && key == p2 {
2054 entity.add(93); }
2056 });
2057
2058 assert_eq!(world.enemy.get(e1).unwrap().hp, 100);
2060 assert_eq!(world.player.get(p1).unwrap().id, 100);
2061 assert_eq!(world.player.get(p2).unwrap().id, 100);
2062 }
2063
2064 #[test]
2065 fn visit_key_ordering_with_arena_ids() {
2066 let mut world = MyWorld::default();
2067
2068 let e1 = world.enemy.insert(Enemy { hp: 1 });
2070 let e2 = world.enemy.insert(Enemy { hp: 2 });
2071 let p1 = world.player.insert(Player { id: 3 });
2072 let p2 = world.player.insert(Player { id: 4 });
2073
2074 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2075 let player_arena_id = MyWorld::arena_id::<Player>();
2076
2077 let mut arena_key_pairs = Vec::new();
2079 world.visit_key_test_trait(|(arena_id, key), _| {
2080 arena_key_pairs.push((arena_id, key));
2081 });
2082
2083 assert_eq!(arena_key_pairs, vec![
2085 (enemy_arena_id, e1),
2086 (enemy_arena_id, e2),
2087 (player_arena_id, p1),
2088 (player_arena_id, p2),
2089 ]);
2090 }
2091
2092 #[test]
2093 fn visit_key_with_selective_trait_arena_ids() {
2094 let mut world = MyWorld::default();
2095
2096 let _e1 = world.enemy.insert(Enemy { hp: 10 });
2097 let p1 = world.player.insert(Player { id: 5 });
2098 let p2 = world.player.insert(Player { id: 7 });
2099
2100 let player_arena_id = MyWorld::arena_id::<Player>();
2101
2102 let mut player_data = Vec::new();
2104 world.visit_key_second_test_trait(|(arena_id, key), _| {
2105 player_data.push((arena_id, key));
2106 });
2107
2108 assert_eq!(player_data.len(), 2);
2110 assert!(player_data.contains(&(player_arena_id, p1)));
2111 assert!(player_data.contains(&(player_arena_id, p2)));
2112 }
2113
2114 #[test]
2115 fn visit_key_mut_selective_modification_by_arena_id() {
2116 let mut world = MyWorld::default();
2117
2118 world.enemy.insert(Enemy { hp: 10 });
2119 world.enemy.insert(Enemy { hp: 20 });
2120 let p1 = world.player.insert(Player { id: 5 });
2121 let p2 = world.player.insert(Player { id: 7 });
2122
2123 let player_arena_id = MyWorld::arena_id::<Player>();
2124
2125 world.visit_key_mut_second_test_trait(|(arena_id, _key), entity| {
2127 assert_eq!(arena_id, player_arena_id);
2128 entity.touch(); });
2130
2131 assert_eq!(world.player.get(p1).unwrap().id, 1005);
2133 assert_eq!(world.player.get(p2).unwrap().id, 1007);
2134
2135 let enemy_hps: Vec<i32> = world.enemy.values().map(|e| e.hp).collect();
2137 assert_eq!(enemy_hps, vec![10, 20]);
2138 }
2139
2140 #[test]
2141 fn visit_key_empty_world_no_arena_ids() {
2142 let world = MyWorld::default();
2143
2144 let mut visited = false;
2145 world.visit_key_test_trait(|(_arena_id, _key), _entity| {
2146 visited = true;
2147 });
2148
2149 assert!(!visited);
2150 }
2151
2152 #[cfg(feature = "rayon")]
2153 #[test]
2154 fn par_visit_key_mut_concurrent_modification_with_arena_ids() {
2155 use std::sync::atomic::{AtomicI32, Ordering};
2156
2157 let mut world = MyWorld::default();
2158
2159 let player_arena_id = MyWorld::arena_id::<Player>();
2160
2161 for i in 0..100 {
2163 world.player.insert(Player { id: i });
2164 }
2165
2166 let modification_count = AtomicI32::new(0);
2167
2168 world.par_visit_key_mut_test_trait(|(arena_id, _key), entity| {
2170 assert_eq!(arena_id, player_arena_id);
2171 entity.add(1000);
2172 modification_count.fetch_add(1, Ordering::Relaxed);
2173 });
2174
2175 assert_eq!(modification_count.load(Ordering::Relaxed), 100);
2177
2178 for player in world.player.values() {
2180 assert!(player.id >= 1000 && player.id < 1100);
2181 }
2182 }
2183
2184 #[cfg(feature = "rayon")]
2185 #[test]
2186 fn par_visit_key_ordering_deterministic_with_arena_ids() {
2187 let mut world = MyWorld::default();
2188
2189 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2190 let player_arena_id = MyWorld::arena_id::<Player>();
2191
2192 let mut expected_pairs = Vec::new();
2194 for i in 0..50 {
2195 expected_pairs.push((enemy_arena_id, world.enemy.insert(Enemy { hp: i })));
2196 expected_pairs.push((player_arena_id, world.player.insert(Player { id: i })));
2197 }
2198
2199 let mut seq_pairs = Vec::new();
2201 world.visit_key_test_trait(|(arena_id, key), _| {
2202 seq_pairs.push((arena_id, key));
2203 });
2204
2205 for _ in 0..5 {
2207 let mut par_pairs = Vec::new();
2208 world.visit_key_test_trait(|(arena_id, key), _| {
2209 par_pairs.push((arena_id, key));
2210 });
2211
2212 assert_eq!(par_pairs, seq_pairs);
2214 }
2215 }
2216
2217 #[test]
2218 fn visit_key_with_removal_during_iteration_arena_ids() {
2219 let mut world = MyWorld::default();
2220
2221 let e1 = world.enemy.insert(Enemy { hp: 10 });
2222 let e2 = world.enemy.insert(Enemy { hp: 20 });
2223 let p1 = world.player.insert(Player { id: 5 });
2224
2225 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2226 let player_arena_id = MyWorld::arena_id::<Player>();
2227
2228 let mut to_remove = Vec::new();
2230 world.visit_key_test_trait(|(arena_id, key), entity| {
2231 if entity.metric() > 10 {
2232 to_remove.push((arena_id, key));
2233 }
2234 });
2235
2236 for (arena_id, key) in to_remove {
2238 if arena_id == enemy_arena_id {
2239 world.enemy.remove(key);
2240 } else if arena_id == player_arena_id {
2241 world.player.remove(key);
2242 }
2243 }
2244
2245 assert!(world.enemy.get(e1).is_some()); assert!(world.enemy.get(e2).is_none()); assert!(world.player.get(p1).is_some()); }
2250
2251 #[test]
2252 fn visit_key_mut_with_arena_id_dependent_logic() {
2253 let mut world = MyWorld::default();
2254
2255 let e1 = world.enemy.insert(Enemy { hp: 10 });
2256 let e2 = world.enemy.insert(Enemy { hp: 20 });
2257 let p1 = world.player.insert(Player { id: 5 });
2258
2259 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2260 let target_key = e2;
2261
2262 world.visit_key_mut_test_trait(|(arena_id, key), entity| {
2264 if arena_id == enemy_arena_id && key == target_key {
2265 entity.add(1000);
2266 }
2267 });
2268
2269 assert_eq!(world.enemy.get(e1).unwrap().hp, 10);
2271 assert_eq!(world.enemy.get(e2).unwrap().hp, 1020);
2272 assert_eq!(world.player.get(p1).unwrap().id, 5);
2273 }
2274
2275 #[test]
2276 fn visit_key_distinguishes_same_key_different_arenas() {
2277 let mut world = MyWorld::default();
2279
2280 world.clear();
2282
2283 let e_key = world.enemy.insert(Enemy { hp: 100 });
2284 let p_key = world.player.insert(Player { id: 200 });
2285
2286 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2287 let player_arena_id = MyWorld::arena_id::<Player>();
2288
2289 let mut visited = Vec::new();
2291 world.visit_key_test_trait(|(arena_id, key), entity| {
2292 visited.push((arena_id, key, entity.metric()));
2293 });
2294
2295 assert!(visited.contains(&(enemy_arena_id, e_key, 100)));
2297 assert!(visited.contains(&(player_arena_id, p_key, 200)));
2298 assert_eq!(visited.len(), 2);
2299 }
2300
2301 #[cfg(feature = "rayon")]
2302 #[test]
2303 fn par_visit_key_correct_arena_ids_per_spawn() {
2304 use std::sync::{Arc, Mutex};
2305
2306 let mut world = MyWorld::default();
2307
2308 let enemy_arena_id = MyWorld::arena_id::<Enemy>();
2309 let player_arena_id = MyWorld::arena_id::<Player>();
2310
2311 for i in 0..100 {
2313 world.enemy.insert(Enemy { hp: i });
2314 world.player.insert(Player { id: i + 100 });
2315 }
2316
2317 let collected = Arc::new(Mutex::new(Vec::new()));
2318 let collected_clone = Arc::clone(&collected);
2319
2320 world.par_visit_key_test_trait(move |(arena_id, _key), entity| {
2322 collected_clone.lock().unwrap().push((arena_id, entity.metric()));
2323 });
2324
2325 let results = collected.lock().unwrap();
2326
2327 let enemy_results: Vec<_> = results.iter()
2329 .filter(|(aid, _)| *aid == enemy_arena_id)
2330 .map(|(_, m)| *m)
2331 .collect();
2332 assert_eq!(enemy_results.len(), 100);
2333 assert!(enemy_results.iter().all(|m| *m < 100));
2334
2335 let player_results: Vec<_> = results.iter()
2337 .filter(|(aid, _)| *aid == player_arena_id)
2338 .map(|(_, m)| *m)
2339 .collect();
2340 assert_eq!(player_results.len(), 100);
2341 assert!(player_results.iter().all(|m| *m >= 100));
2342 }
2343}