1#![allow(incomplete_features)]
5#![feature(specialization)]
6#![forbid(unsafe_code)]
7
8#[cfg(feature = "serde")]
10#[doc(hidden)]
11pub use once_cell;
12#[doc(hidden)]
13pub use paste;
14#[cfg(feature = "rayon")]
15#[doc(hidden)]
16pub use rayon;
17#[cfg(feature = "serde")]
18#[doc(hidden)]
19pub use serde;
20#[doc(hidden)]
21pub use slotmap;
22
23#[doc(hidden)]
25pub trait IsType<T> {
26 const VALUE: bool = false;
27}
28
29impl<A, B> IsType<B> for A {
30 default const VALUE: bool = false;
31}
32
33impl<T> IsType<T> for T {
35 const VALUE: bool = true;
36}
37
38#[doc(hidden)]
39pub trait ArenaCast<T> {
40 fn cast(&self) -> &slotmap::DenseSlotMap<slotmap::DefaultKey, T>;
41 fn cast_mut(&mut self) -> &mut slotmap::DenseSlotMap<slotmap::DefaultKey, T>;
42}
43
44impl<A, B> ArenaCast<B> for slotmap::DenseSlotMap<slotmap::DefaultKey, A> {
46 default fn cast(&self) -> &slotmap::DenseSlotMap<slotmap::DefaultKey, B> {
47 panic!( "Arena type mismatch: {} cannot be cast to {}",
49 std::any::type_name::<A>(),
50 std::any::type_name::<B>()
51 );
52 }
53
54 default fn cast_mut(&mut self) -> &mut slotmap::DenseSlotMap<slotmap::DefaultKey, B> {
55 panic!( "Arena type mismatch: {} cannot be cast to {}",
57 std::any::type_name::<A>(),
58 std::any::type_name::<B>()
59 );
60 }
61}
62
63impl<T> ArenaCast<T> for slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
65 fn cast(&self) -> &slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
66 self
67 }
68
69 fn cast_mut(&mut self) -> &mut slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
70 self
71 }
72}
73
74#[cfg(feature = "serde")]
76#[doc(hidden)] pub trait SerdeArena<'de> {
78 fn serialize_arena<S>(&self, field_name: &'static str, state: &mut S) -> Result<(), S::Error>
80 where
81 S: serde::ser::SerializeStruct;
82
83 fn deserialize_arena<M>(map: &mut M) -> Result<Self, M::Error>
85 where
86 M: serde::de::MapAccess<'de>,
87 Self: Sized;
88
89 fn from_seq<V>(seq: &mut V, field_name: &str) -> Result<Self, V::Error>
91 where
92 V: serde::de::SeqAccess<'de>,
93 Self: Sized;
94
95 const ACTIVE: bool; }
97
98#[cfg(feature = "serde")]
100impl<'de, T> SerdeArena<'de> for slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
101 default fn serialize_arena<S>(
102 &self,
103 _field_name: &'static str,
104 _state: &mut S,
105 ) -> Result<(), S::Error>
106 where
107 S: serde::ser::SerializeStruct,
108 {
109 Ok(())
110 }
111
112 default fn deserialize_arena<M>(_map: &mut M) -> Result<Self, M::Error>
113 where
114 M: serde::de::MapAccess<'de>,
115 {
116 Ok(slotmap::DenseSlotMap::new())
117 }
118
119 default fn from_seq<V>(_seq: &mut V, _field_name: &str) -> Result<Self, V::Error>
120 where
121 V: serde::de::SeqAccess<'de>,
122 {
123 Ok(slotmap::DenseSlotMap::new())
124 }
125
126 default const ACTIVE: bool = false;
127}
128
129#[cfg(feature = "serde")]
131impl<'de, T> SerdeArena<'de> for slotmap::DenseSlotMap<slotmap::DefaultKey, T>
132where
133 T: serde::Serialize + serde::Deserialize<'de>,
134{
135 fn serialize_arena<S>(&self, field_name: &'static str, state: &mut S) -> Result<(), S::Error>
136 where
137 S: serde::ser::SerializeStruct,
138 {
139 state.serialize_field(field_name, self)
140 }
141
142 fn deserialize_arena<M>(map: &mut M) -> Result<Self, M::Error>
143 where
144 M: serde::de::MapAccess<'de>,
145 {
146 map.next_value()
147 }
148
149 fn from_seq<V>(seq: &mut V, field_name: &str) -> Result<Self, V::Error>
150 where
151 V: serde::de::SeqAccess<'de>,
152 {
153 seq.next_element()?
154 .ok_or_else(|| serde::de::Error::custom(format!("Missing element for {}", field_name)))
155 }
156
157 const ACTIVE: bool = true;
158}
159
160pub trait ErasedArena {
162 fn get_any(&self, key: slotmap::DefaultKey) -> Option<&dyn std::any::Any>;
163 fn get_any_mut(&mut self, key: slotmap::DefaultKey) -> Option<&mut dyn std::any::Any>;
164}
165
166impl<T: 'static> ErasedArena for slotmap::DenseSlotMap<slotmap::DefaultKey, T> {
167 fn get_any(&self, key: slotmap::DefaultKey) -> Option<&dyn std::any::Any> {
168 self.get(key).map(|e| e as &dyn std::any::Any)
169 }
170
171 fn get_any_mut(&mut self, key: slotmap::DefaultKey) -> Option<&mut dyn std::any::Any> {
172 self.get_mut(key).map(|e| e as &mut dyn std::any::Any)
173 }
174}
175
176#[macro_export]
177#[cfg(not(feature = "rayon"))]
178macro_rules! __world_define_rayon_trait_helpers {
179 ($( $trait_name:ident ),*) => {};
180}
181
182#[macro_export]
183#[cfg(feature = "rayon")]
184macro_rules! __world_define_rayon_trait_helpers {
185 ($( $trait_name:ident ),*) => {
186 $crate::paste::paste! {
187
188$(
189trait [<ParVisitIf $trait_name>]<T> {
190 fn par_visit_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
191 where
192 F: Fn(&dyn $trait_name) + Send + Sync;
193
194 fn par_visit_if_applicable_mut<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
195 where
196 F: Fn(&mut dyn $trait_name) + Send + Sync;
197}
198
199impl<T> [<ParVisitIf $trait_name>]<T> for () {
200 default fn par_visit_if_applicable<F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F)
201 where F: Fn(&dyn $trait_name) + Send + Sync {}
202
203 default fn par_visit_if_applicable_mut<F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: &F)
204 where F: Fn(&mut dyn $trait_name) + Send + Sync {}
205}
206
207impl<T> [<ParVisitIf $trait_name>]<T> for ()
208where
209 T: $trait_name + Send + Sync,
210{
211 fn par_visit_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
212 where F: Fn(&dyn $trait_name) + Send + Sync
213 {
214 use $crate::rayon::iter::IntoParallelRefIterator;
215 use $crate::rayon::iter::ParallelIterator;
216 arena
217 .values_as_slice()
218 .par_iter()
219 .for_each(|entity| handler(entity as &dyn $trait_name));
220 }
221
222 fn par_visit_if_applicable_mut<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: &F)
223 where F: Fn(&mut dyn $trait_name) + Send + Sync
224 {
225 use $crate::rayon::iter::IntoParallelRefMutIterator;
226 use $crate::rayon::iter::ParallelIterator;
227 arena
228 .values_as_mut_slice()
229 .par_iter_mut()
230 .for_each(|entity| handler(entity as &mut dyn $trait_name));
231 }
232}
233
234)*
235 }
236 };
237}
238
239#[macro_export]
240macro_rules! __world_define_visitors_common {
241 (@pass_entity_tuple $($trait_name:ident),* @ $entity_tuple:tt) => {
245 $crate::paste::paste! {
246 $(
247 #[allow(unused)]
248 pub fn [<visit_ $trait_name:snake>]<F>(&self, mut handler: F)
249 where
250 F: FnMut(&dyn $trait_name)
251 {
252 $crate::__world_define_visitors_common!(@use_entity_tuple $trait_name $entity_tuple self handler);
253 }
254
255 #[allow(unused)]
256 pub fn [<visit_mut_ $trait_name:snake>]<F>(&mut self, mut handler: F)
257 where
258 F: FnMut(&mut dyn $trait_name)
259 {
260 $crate::__world_define_visitors_common!(@use_entity_tuple_mut $trait_name $entity_tuple self handler);
261 }
262 )*
263 }
264 };
265
266 (@use_entity_tuple $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
267 $crate::paste::paste! {
268 $(
269 <() as [<VisitIf $trait_name>]<$entity>>::visit_if_applicable(
270 &$self_ident.[<$entity:snake>],
271 &mut $handler_ident,
272 );
273 )*
274 }
275 };
276
277 (@use_entity_tuple_mut $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
278 $crate::paste::paste! {
279 $(
280 <() as [<VisitIf $trait_name>]<$entity>>::visit_if_applicable_mut(
281 &mut $self_ident.[<$entity:snake>],
282 &mut $handler_ident,
283 );
284 )*
285 }
286 };
287}
288
289#[macro_export]
290#[cfg(not(feature = "rayon"))]
291macro_rules! __world_define_visitors {
292 (@pass_entity_tuple $($trait_name:ident),* @ $entity_tuple:tt) => {
294 $crate::__world_define_visitors_common!(@pass_entity_tuple $($trait_name),* @ $entity_tuple);
295 };
296}
297
298#[macro_export]
299#[cfg(feature = "rayon")]
300macro_rules! __world_define_visitors {
301 (@pass_entity_tuple $($trait_name:ident),* @ $entity_tuple:tt) => {
305 $crate::__world_define_visitors_common!(@pass_entity_tuple $($trait_name),* @ $entity_tuple);
307
308 $crate::paste::paste! {
310 $(
311 #[allow(unused)]
312 pub fn [<par_visit_ $trait_name:snake>]<F>(&self, handler: F)
313 where
314 F: Fn(&dyn $trait_name) + Send + Sync
315 {
316 $crate::__world_define_visitors!(@use_entity_tuple_par $trait_name $entity_tuple self handler);
317 }
318
319 #[allow(unused)]
320 pub fn [<par_visit_mut_ $trait_name:snake>]<F>(&mut self, handler: F)
321 where
322 F: Fn(&mut dyn $trait_name) + Send + Sync
323 {
324 $crate::__world_define_visitors!(@use_entity_tuple_par_mut $trait_name $entity_tuple self handler);
325 }
326 )*
327 }
328 };
329
330 (@use_entity_tuple_par $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
331 $crate::paste::paste! {
332 use $crate::rayon::scope;
333 scope(|s| {
334 $(
335 let arena_ref = &$self_ident.[<$entity:snake>];
336 s.spawn(|_| {
337 <() as [<ParVisitIf $trait_name>]<$entity>>::par_visit_if_applicable(
338 arena_ref,
339 &$handler_ident,
340 );
341 });
342 )*
343
344 });
345 }
346 };
347
348 (@use_entity_tuple_par_mut $trait_name:ident ($( $entity:ty ),*) $self_ident:ident $handler_ident:ident) => {
349 $crate::paste::paste! {
350 use $crate::rayon::scope;
351 scope(|s| {
352 $(
353 let arena_ref = &mut $self_ident.[<$entity:snake>];
354 let handler_ref = &$handler_ident;
355 s.spawn(|_| {
356 <() as [<ParVisitIf $trait_name>]<$entity>>::par_visit_if_applicable_mut(
357 arena_ref,
358 handler_ref,
359 );
360 });
361 )*
362 });
363 }
364 };
365}
366
367#[macro_export]
368#[cfg(not(feature = "debug"))]
369macro_rules! __world_define_struct {
370 ($struct_name:ident, $( $entity:ty ),*) => {
371 $crate::paste::paste! {
372 #[derive(Default)]
373 #[allow(private_interfaces)] pub struct $struct_name {
375 $(
376 pub [<$entity:snake>]: $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity>,
377 )*
378 }
379 }
380 };
381}
382
383#[macro_export]
384#[cfg(feature = "debug")]
385macro_rules! __world_define_struct {
386 ($struct_name:ident, $( $entity:ty ),*) => {
387 $crate::paste::paste! {
388 #[derive(Default, Debug)]
389 #[allow(private_interfaces)] pub struct $struct_name {
391 $(
392 pub [<$entity:snake>]: $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity>,
393 )*
394 }
395 }
396 };
397}
398
399#[macro_export]
400#[cfg(not(feature = "serde"))]
401macro_rules! __world_serde_support {
402 ($struct_name:ident, $( $entity:ty ),*) => {};
403}
404
405#[macro_export]
406#[cfg(feature = "serde")]
407macro_rules! __world_serde_support {
408 ($struct_name:ident, $( $entity:ty ),*) => {
409 $crate::paste::paste! {
410
411impl $crate::serde::Serialize for [<$struct_name ArenaID>] {
412 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
413 where
414 S: $crate::serde::Serializer,
415 {
416 let s = match self.0 {
417 $(
418 i if i == $struct_name::arena_id::<$entity>().0 => stringify!($entity),
419 )*
420 _ => return Err($crate::serde::ser::Error::custom(format!("Unknown ArenaID {}", self.0))),
422 };
423 serializer.serialize_str(s)
424 }
425}
426
427impl<'de> $crate::serde::Deserialize<'de> for [<$struct_name ArenaID>] {
428 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
429 where
430 D: $crate::serde::Deserializer<'de>,
431 {
432 let s = String::deserialize(deserializer)?;
433 let id = match s.as_str() {
434 $(
435 stringify!($entity) => $struct_name::arena_id::<$entity>().0,
436 )*
437 _ => return Err($crate::serde::de::Error::custom(format!("Unknown ArenaID string {}", s))),
439 };
440 Ok([<$struct_name ArenaID>](id))
441 }
442}
443
444impl $crate::serde::ser::Serialize for $struct_name {
445 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
446 where
447 S: $crate::serde::ser::Serializer,
448 {
449 use $crate::SerdeArena;
450 use $crate::serde::ser::SerializeStruct;
451
452 let field_count = 0 $( + if <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'static>>::ACTIVE { 1 } else { 0 } )*;
453 let mut state = serializer.serialize_struct(
454 stringify!($struct_name),
455 field_count
456 )?;
457 $(
458 self.[<$entity:snake>].serialize_arena(stringify!($entity), &mut state)?;
459 )*
460 state.end()
461 }
462}
463
464static [<$struct_name:upper _DESERIALIZE_FIELDS>]: $crate::once_cell::sync::Lazy<Vec<&'static str>> =
466 $crate::once_cell::sync::Lazy::new(|| {
467 vec![
468 $(
469 if <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'static>>::ACTIVE {
470 Some(stringify!($entity))
471 } else {
472 None
473 }
474 ),*
475 ]
476 .into_iter()
477 .flatten() .collect()
479 });
480
481
482impl<'de> $crate::serde::Deserialize<'de> for $struct_name {
483 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
484 where
485 D: $crate::serde::Deserializer<'de>,
486 {
487 use $crate::serde::de::{MapAccess, SeqAccess, Visitor, Error};
488 use std::fmt;
489
490 struct WorldVisitor;
491
492 impl<'de> Visitor<'de> for WorldVisitor {
493 type Value = $struct_name;
494
495 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
496 write!(f, "struct {}", stringify!($struct_name))
497 }
498
499 fn visit_map<V>(self, mut map: V) -> Result<$struct_name, V::Error>
501 where
502 V: MapAccess<'de>,
503 {
504 let mut world = $struct_name::default();
505
506 while let Some(key) = map.next_key::<String>()? {
507 match key.as_str() {
508 $(
509 stringify!($entity) => {
510 world.[<$entity:snake>] =
511 <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'de>>::deserialize_arena(&mut map)?;
512 }
513 )*
514 other => {
515 return Err(V::Error::custom(format!(
516 "Unknown field '{}' for {}",
517 other,
518 stringify!($struct_name)
519 )));
520 }
521 }
522 }
523
524 Ok(world)
525 }
526
527 fn visit_seq<V>(self, mut seq: V) -> Result<$struct_name, V::Error>
530 where
531 V: SeqAccess<'de>,
532 {
533 Ok($struct_name {
534 $(
535 [<$entity:snake>]: <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as $crate::SerdeArena<'de>>::from_seq(&mut seq, stringify!($entity))?,
536 )*
537 })
538 }
539 }
540
541 deserializer.deserialize_struct(
546 stringify!($struct_name),
547 &[<$struct_name:upper _DESERIALIZE_FIELDS>],
548 WorldVisitor,
549 )
550 }
551}
552 }
553 };
554}
555
556#[macro_export]
557macro_rules! world {
558 (
560 $struct_name:ident, $( $entity:ty ),* $(,)? ;$( $trait_name:ident ),* $(,)? ) => {
567 $crate::paste::paste! {
568
569#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
577pub struct [<$struct_name ArenaID>](usize);
578
579$crate::__world_define_struct!($struct_name, $($entity),*);
580
581$(
582 trait [<VisitIf $trait_name>]<T> {
583 fn visit_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F)
584 where
585 F: FnMut(&dyn $trait_name);
586
587 fn visit_if_applicable_mut<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, handler: F)
588 where
589 F: FnMut(&mut dyn $trait_name);
590 }
591
592 impl<T> [<VisitIf $trait_name>]<T> for () {
594 default fn visit_if_applicable<F>(_arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F)
595 where F: FnMut(&dyn $trait_name) {}
596
597 default fn visit_if_applicable_mut<F>(_arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, _handler: F)
598 where F: FnMut(&mut dyn $trait_name) {}
599 }
600
601 impl<T: $trait_name> [<VisitIf $trait_name>]<T> for () {
602 fn visit_if_applicable<F>(arena: &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F)
603 where F: FnMut(&dyn $trait_name)
604 {
605 arena
606 .values_as_slice()
607 .iter()
608 .for_each(|entity| handler(entity as &dyn $trait_name));
609 }
610
611 fn visit_if_applicable_mut<F>(arena: &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T>, mut handler: F)
612 where F: FnMut(&mut dyn $trait_name)
613 {
614 arena
615 .values_as_mut_slice()
616 .iter_mut()
617 .for_each(|entity| handler(entity as &mut dyn $trait_name));
618 }
619 }
620
621)*
622
623impl $struct_name {
624 $crate::__world_define_visitors!(@pass_entity_tuple $($trait_name),* @ ($($entity),*));
625
626 #[allow(unused)]
627 pub fn arena<T>(&self) -> &$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T> {
628 use $crate::ArenaCast;
629 $(
630 if <T as $crate::IsType<$entity>>::VALUE {
631 return <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as ArenaCast<T>>::cast(&self.[<$entity:snake>]);
632 }
633 )*
634 panic!("In call to {}::arena::<{}>(), {} not registered", stringify!($struct_name), std::any::type_name::<T>(), std::any::type_name::<T>());
635 }
636
637 #[allow(unused)]
638 pub fn arena_mut<T>(&mut self) -> &mut $crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, T> {
639 use $crate::ArenaCast;
640 $(
641 if <T as $crate::IsType<$entity>>::VALUE {
642 return <$crate::slotmap::DenseSlotMap<$crate::slotmap::DefaultKey, $entity> as ArenaCast<T>>::cast_mut(&mut self.[<$entity:snake>]);
643 }
644 )*
645 panic!("In call to {}::arena_mut::<{}>(), {} not registered", stringify!($struct_name), std::any::type_name::<T>(), std::any::type_name::<T>());
646 }
647
648
649 pub fn arena_id<T>() -> [<$struct_name ArenaID>] {
650 let mut i = 0usize;
651 $(
652 if <T as $crate::IsType<$entity>>::VALUE {
653 return [<$struct_name ArenaID>](i);
654 }
655 i += 1;
656 )*
657 panic!("In call to {}::arena_id::<{}>(), {} not registered", stringify!($struct_name), std::any::type_name::<T>(), std::any::type_name::<T>());
658 }
659
660 #[allow(unused)]
661 pub fn arena_erased(&self, id: [<$struct_name ArenaID>]) -> &dyn $crate::ErasedArena {
662 match id.0 {
663 $(
664 i if i == Self::arena_id::<$entity>().0 => &self.[<$entity:snake>] as &dyn $crate::ErasedArena,
665 )*
666 _ => panic!("No arena for type id {}", id.0),
667 }
668 }
669
670 #[allow(unused)]
671 pub fn arena_erased_mut(&mut self, id: [<$struct_name ArenaID>]) -> &mut dyn $crate::ErasedArena {
672 match id.0 {
673 $(
674 i if i == Self::arena_id::<$entity>().0 => &mut self.[<$entity:snake>] as &mut dyn $crate::ErasedArena,
675 )*
676 _ => panic!("No arena for type id {}", id.0),
677 }
678 }
679}
680
681$crate::__world_serde_support!($struct_name, $($entity),*);
682
683$crate::__world_define_rayon_trait_helpers!($($trait_name),*);
684
685 }
686 };
687}
688
689#[cfg(test)]
693mod tests {
694 #[derive(Debug)]
695 #[cfg_attr(
696 feature = "serde",
697 derive(serde::Serialize, serde::Deserialize, bincode::Encode, bincode::Decode)
698 )]
699 struct Player {
700 id: u32,
701 }
702 #[derive(Debug)]
703 #[cfg_attr(
705 feature = "serde",
706 derive(serde::Serialize, serde::Deserialize, bincode::Encode, bincode::Decode)
707 )]
708 struct Enemy {
709 hp: u32,
710 }
711
712 pub trait TestTrait {
713 fn do_something(&self);
714 }
715 impl TestTrait for Player {
716 fn do_something(&self) {
717 println!("Player {}", self.id)
718 }
719 }
720 impl TestTrait for Enemy {
721 fn do_something(&self) {
722 println!("Enemy {}", self.hp)
723 }
724 }
725
726 pub trait SecondTestTrait {
727 fn do_something_else(&mut self);
728 }
729 impl SecondTestTrait for Player {
730 fn do_something_else(&mut self) {
731 println!("Player second trait")
732 }
733 }
734
735 world!(MyWorld, Enemy, Player; TestTrait, SecondTestTrait);
736
737 #[test]
738 fn do_tests() {
739 let mut world = MyWorld::default();
740 let player_id = world.player.insert(Player { id: 1 });
742 world.arena_mut::<Enemy>().insert(Enemy { hp: 10 });
744
745 #[cfg(feature = "rayon")]
749 world.par_visit_test_trait(|e| e.do_something());
750 #[cfg(not(feature = "rayon"))]
751 world.visit_test_trait(|e| e.do_something());
752
753 #[cfg(feature = "rayon")]
754 world.par_visit_mut_second_test_trait(|e| e.do_something_else());
755 #[cfg(not(feature = "rayon"))]
756 world.visit_mut_second_test_trait(|e| e.do_something_else());
757
758 let arena_id = MyWorld::arena_id::<Player>();
761 let arena = world.arena_erased(arena_id);
762 let player = arena
764 .get_any(player_id)
765 .unwrap()
766 .downcast_ref::<Player>()
767 .unwrap();
768 player.do_something();
769
770 #[cfg(all(feature = "serde", feature = "debug"))]
771 {
772 println!("testing serialization round trips");
773 let serialized = serde_json::to_string(&world).unwrap();
775 let deserialized_json: MyWorld = serde_json::from_str(&serialized).unwrap();
776
777 let serialized: Vec<u8> =
778 bincode::serde::encode_to_vec(&world, bincode::config::standard()).unwrap();
779 let (deserialized_bincode, _bytes_read): (MyWorld, usize) =
780 bincode::serde::decode_from_slice(&serialized, bincode::config::standard())
781 .unwrap();
782
783 assert_eq!(format!("{:?}", world), format!("{:?}", deserialized_json));
784 assert_eq!(
785 format!("{:?}", world),
786 format!("{:?}", deserialized_bincode)
787 );
788 }
789 }
790}