1use std::any::TypeId;
2use std::collections::HashMap;
3use std::convert::TryInto;
4use std::hash::{BuildHasherDefault, Hasher};
5use std::mem::transmute_copy;
6use std::num::NonZeroU32;
7use std::process::abort;
8use std::sync::atomic::{AtomicU32, Ordering};
9
10use crate::{
11 archetype::{Archetype, Cloner, TypeMetadataSet},
12 borrow_flags::BorrowFlags,
13 query::{Fetch, FetchShared, QuerySpec},
14};
15
16pub struct World {
18 tag: u32,
19 pub(crate) entities: Vec<EntityMetadata>,
20 free_list: Vec<u32>,
21 pub(crate) borrow_flags: BorrowFlags,
22 pub(crate) archetypes: Vec<Archetype>,
23 exchange_map: IndexTypeIdMap<u16>,
24 transfer_map: IndexTagMap<u16>,
25}
26
27impl Default for World {
28 fn default() -> Self {
30 Self::new()
31 }
32}
33
34impl World {
35 pub fn new() -> Self {
37 let mut empty_archetype = TypeMetadataSet::default();
38 empty_archetype.insert::<Entity>();
39
40 let mut borrow_flags = BorrowFlags::default();
41 borrow_flags.insert(&empty_archetype);
42
43 let archetypes = vec![Archetype::new(empty_archetype)];
44
45 Self {
46 tag: tag(),
47 entities: Default::default(),
48 free_list: Default::default(),
49 borrow_flags,
50 archetypes,
51 exchange_map: Default::default(),
52 transfer_map: Default::default(),
53 }
54 }
55}
56
57fn tag() -> u32 {
58 static TAG: AtomicU32 = AtomicU32::new(0);
59
60 TAG.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |tag| {
61 tag.checked_add(1)
62 })
63 .unwrap()
64}
65
66impl World {
67 #[must_use]
80 pub fn alloc(&mut self) -> Entity {
81 let id = self.alloc_id();
82
83 let meta = &mut self.entities[id as usize];
84 let archetype = &mut self.archetypes[0];
85
86 meta.ty = 0;
87 meta.idx = unsafe { archetype.alloc() };
88
89 let ent = Entity { id, gen: meta.gen };
90
91 unsafe {
92 archetype.get::<Entity>(meta.idx).write(ent);
93 }
94
95 ent
96 }
97
98 fn alloc_id(&mut self) -> u32 {
99 if let Some(id) = self.free_list.pop() {
100 id
101 } else {
102 let id = self.entities.len().try_into().unwrap();
103 self.entities.push(Default::default());
104 id
105 }
106 }
107
108 pub fn free(&mut self, ent: Entity) {
123 let meta = &mut self.entities[ent.id as usize];
124 assert_eq!(ent.gen, meta.gen, "Entity is stale");
125
126 meta.bump_gen();
127
128 Self::free_idx::<true>(
129 &mut self.archetypes[meta.ty as usize],
130 meta.idx,
131 &mut self.entities,
132 );
133
134 self.free_list.push(ent.id);
135 }
136
137 fn free_idx<const DROP: bool>(
138 archetype: &mut Archetype,
139 idx: u32,
140 entities: &mut [EntityMetadata],
141 ) {
142 unsafe {
143 if archetype.free::<DROP>(idx) {
144 let swapped_ent = archetype.get::<Entity>(idx).read();
145
146 entities[swapped_ent.id as usize].idx = idx;
147 }
148 }
149 }
150
151 pub fn clear(&mut self) {
156 self.entities.clear();
157 self.free_list.clear();
158
159 for archetype in &mut *self.archetypes {
160 archetype.clear();
161 }
162 }
163}
164
165impl World {
166 pub(crate) fn tag_gen(&self) -> (u32, u16) {
167 debug_assert!(!self.archetypes.is_empty());
168 (self.tag, self.archetypes.len() as u16)
169 }
170
171 pub fn insert<B>(&mut self, ent: Entity, comps: B)
186 where
187 B: Bundle,
188 {
189 self.exchange::<(), B>(ent, comps);
190 }
191
192 pub fn remove<B>(&mut self, ent: Entity) -> Option<B>
207 where
208 B: Bundle,
209 {
210 self.exchange::<B, ()>(ent, ())
211 }
212
213 pub fn exchange<B1, B2>(&mut self, ent: Entity, new_comps: B2) -> Option<B1>
233 where
234 B1: Bundle,
235 B2: Bundle,
236 {
237 let meta = &self.entities[ent.id as usize];
238 assert_eq!(ent.gen, meta.gen, "Entity is stale");
239
240 let key = TypeId::of::<(B1, B2)>();
241
242 let new_ty = if let Some(ty) = self.exchange_map.get(&(meta.ty, key)) {
243 *ty
244 } else {
245 Self::exchange_cold(
246 &mut self.archetypes,
247 &mut self.borrow_flags,
248 &mut self.exchange_map,
249 key,
250 B1::remove,
251 B2::insert,
252 meta.ty,
253 )?
254 };
255
256 let old_ty = meta.ty;
257 let old_idx = meta.idx;
258
259 unsafe {
260 let old_archetype = &mut self.archetypes[old_ty as usize];
261 let old_comps = B1::read(old_archetype, old_idx);
262 B2::drop::<B1>(old_archetype, old_idx);
263
264 let new_idx = self.move_(ent.id, old_ty, new_ty, old_idx);
265
266 let new_archetype = &mut self.archetypes[new_ty as usize];
267 new_comps.write(new_archetype, new_idx);
268
269 Some(old_comps)
270 }
271 }
272
273 #[cold]
274 #[inline(never)]
275 fn exchange_cold(
276 archetypes: &mut Vec<Archetype>,
277 borrow_flags: &mut BorrowFlags,
278 exchange_map: &mut IndexTypeIdMap<u16>,
279 key: TypeId,
280 remove: fn(&mut TypeMetadataSet) -> Option<()>,
281 insert: fn(&mut TypeMetadataSet),
282 old_ty: u16,
283 ) -> Option<u16> {
284 let mut types = archetypes[old_ty as usize].types();
285 remove(&mut types)?;
286 insert(&mut types);
287
288 let new_ty = Self::get_or_insert(archetypes, borrow_flags, types);
289
290 exchange_map.insert((old_ty, key), new_ty);
291
292 Some(new_ty)
293 }
294
295 fn get_or_insert(
296 archetypes: &mut Vec<Archetype>,
297 borrow_flags: &mut BorrowFlags,
298 types: TypeMetadataSet,
299 ) -> u16 {
300 let pos = archetypes
301 .iter()
302 .position(|archetype| archetype.match_(&types));
303
304 if let Some(pos) = pos {
305 pos as u16
306 } else {
307 let len = archetypes.len();
308 assert!(len < u16::MAX as usize);
309
310 borrow_flags.insert(&types);
311
312 archetypes.push(Archetype::new(types));
313
314 len as u16
315 }
316 }
317
318 unsafe fn move_(&mut self, id: u32, old_ty: u16, new_ty: u16, old_idx: u32) -> u32 {
319 if old_ty == new_ty {
320 return old_idx;
321 }
322
323 debug_assert!(self.archetypes.len() > old_ty as usize);
324 debug_assert!(self.archetypes.len() > new_ty as usize);
325
326 let archetypes = self.archetypes.as_mut_ptr();
327 let old_archetype = &mut *archetypes.add(old_ty as usize);
328 let new_archetype = &mut *archetypes.add(new_ty as usize);
329
330 let new_idx = new_archetype.alloc();
331
332 Archetype::move_(old_archetype, new_archetype, old_idx, new_idx);
333
334 Self::free_idx::<false>(old_archetype, old_idx, &mut self.entities);
335
336 let meta = &mut self.entities[id as usize];
337 meta.ty = new_ty;
338 meta.idx = new_idx;
339
340 new_idx
341 }
342}
343
344impl World {
345 pub fn transfer(&mut self, ent: Entity, other: &mut World) -> Entity {
363 let meta = &mut self.entities[ent.id as usize];
364 assert_eq!(ent.gen, meta.gen, "Entity is stale");
365
366 let new_id = other.alloc_id();
368
369 let new_meta = &mut other.entities[new_id as usize];
370
371 meta.bump_gen();
373
374 self.free_list.push(ent.id);
375
376 new_meta.ty = if let Some(ty) = self.transfer_map.get(&(meta.ty, other.tag)) {
378 *ty
379 } else {
380 Self::transfer_cold(
381 &self.archetypes,
382 &mut other.archetypes,
383 &mut other.borrow_flags,
384 &mut self.transfer_map,
385 &mut other.transfer_map,
386 self.tag,
387 other.tag,
388 meta.ty,
389 )
390 };
391
392 let old_archetype = &mut self.archetypes[meta.ty as usize];
394 let new_archetype = &mut other.archetypes[new_meta.ty as usize];
395
396 unsafe {
397 new_meta.idx = new_archetype.alloc();
398
399 Archetype::move_(old_archetype, new_archetype, meta.idx, new_meta.idx);
400
401 Self::free_idx::<false>(old_archetype, meta.idx, &mut self.entities);
402 }
403
404 let ent = Entity {
406 id: new_id,
407 gen: new_meta.gen,
408 };
409
410 unsafe {
411 new_archetype.get::<Entity>(new_meta.idx).write(ent);
412 }
413
414 ent
415 }
416
417 #[allow(clippy::too_many_arguments)]
418 #[cold]
419 #[inline(never)]
420 fn transfer_cold(
421 archetypes: &[Archetype],
422 other_archetypes: &mut Vec<Archetype>,
423 other_borrows: &mut BorrowFlags,
424 transfer_map: &mut IndexTagMap<u16>,
425 other_transfer_map: &mut IndexTagMap<u16>,
426 tag: u32,
427 other_tag: u32,
428 old_ty: u16,
429 ) -> u16 {
430 let types = archetypes[old_ty as usize].types();
431
432 let new_ty = Self::get_or_insert(other_archetypes, other_borrows, types);
433
434 transfer_map.insert((old_ty, other_tag), new_ty);
435 other_transfer_map.insert((new_ty, tag), old_ty);
436
437 new_ty
438 }
439}
440
441impl World {
442 pub fn exists(&self, ent: Entity) -> bool {
457 let meta = &self.entities[ent.id as usize];
458 ent.gen == meta.gen
459 }
460
461 pub fn contains<C>(&self, ent: Entity) -> bool
475 where
476 C: 'static,
477 {
478 let meta = &self.entities[ent.id as usize];
479 assert_eq!(ent.gen, meta.gen, "Entity is stale");
480
481 self.archetypes[meta.ty as usize].find::<C>().is_some()
482 }
483
484 pub fn query_one<S>(&self, ent: Entity) -> Option<QueryOne<'_, S>>
506 where
507 S: QuerySpec,
508 {
509 let meta = &self.entities[ent.id as usize];
510 assert_eq!(ent.gen, meta.gen, "Entity is stale");
511
512 let flags = S::Fetch::find_flags(&self.borrow_flags)?;
513 let _ref = unsafe { S::Fetch::borrow(&self.borrow_flags, flags) };
514
515 let archetype = &self.archetypes[meta.ty as usize];
516
517 let comps = S::Fetch::find_comps(archetype)?;
518 let ptr = unsafe { S::Fetch::base_pointer(archetype, comps) };
519
520 Some(QueryOne {
521 _ref,
522 ptr,
523 idx: meta.idx,
524 })
525 }
526}
527
528impl World {
529 pub fn clone(&mut self, cloner: &Cloner) -> Self {
556 let archetypes = self
557 .archetypes
558 .iter_mut()
559 .map(|archetype| archetype.clone(cloner))
560 .collect();
561
562 Self {
563 tag: tag(),
564 entities: self.entities.clone(),
565 free_list: self.free_list.clone(),
566 borrow_flags: self.borrow_flags.clone(),
567 archetypes,
568 exchange_map: self.exchange_map.clone(),
569 transfer_map: self.transfer_map.clone(),
570 }
571 }
572}
573
574#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
576pub struct Entity {
577 pub(crate) id: u32,
578 pub(crate) gen: NonZeroU32,
579}
580
581#[derive(Clone, Copy)]
582pub struct EntityMetadata {
583 pub gen: NonZeroU32,
584 pub ty: u16,
585 pub idx: u32,
586}
587
588impl Default for EntityMetadata {
589 fn default() -> Self {
590 Self {
591 gen: unsafe { NonZeroU32::new_unchecked(1) },
592 ty: 0,
593 idx: 0,
594 }
595 }
596}
597
598impl EntityMetadata {
599 fn bump_gen(&mut self) {
600 let gen = self.gen.get();
601
602 if gen == u32::MAX {
603 abort();
604 }
605
606 self.gen = unsafe { NonZeroU32::new_unchecked(gen + 1) };
607 }
608}
609
610pub struct QueryOne<'w, S>
612where
613 S: QuerySpec,
614{
615 _ref: <S::Fetch as Fetch<'w>>::Ref,
616 ptr: <S::Fetch as Fetch<'w>>::Ptr,
617 idx: u32,
618}
619
620impl<S> QueryOne<'_, S>
621where
622 S: QuerySpec,
623{
624 pub fn get(&self) -> <S::Fetch as Fetch<'_>>::Item
628 where
629 S::Fetch: FetchShared,
630 {
631 unsafe { S::Fetch::deref(transmute_copy(&self.ptr), self.idx) }
632 }
633
634 pub fn get_mut(&mut self) -> <S::Fetch as Fetch<'_>>::Item {
636 unsafe { S::Fetch::deref(transmute_copy(&self.ptr), self.idx) }
637 }
638}
639
640#[allow(clippy::missing_safety_doc)]
641pub unsafe trait Bundle
642where
643 Self: 'static,
644{
645 fn contains<T>() -> bool
646 where
647 T: 'static;
648
649 fn insert(types: &mut TypeMetadataSet);
650 #[must_use]
651 fn remove(types: &mut TypeMetadataSet) -> Option<()>;
652
653 unsafe fn drop<T>(archetype: &mut Archetype, idx: u32)
654 where
655 T: Bundle;
656
657 unsafe fn write(self, archetype: &mut Archetype, idx: u32);
658 unsafe fn read(archetype: &mut Archetype, idx: u32) -> Self;
659}
660
661macro_rules! impl_bundle_for_tuples {
662 () => {
663 impl_bundle_for_tuples!(@impl);
664 };
665
666 ($head:ident $(,$tail:ident)*) => {
667 impl_bundle_for_tuples!($($tail),*);
668 impl_bundle_for_tuples!(@rev $head $(,$tail)*;);
669 };
670
671 (@rev ; $($rev:ident),*) => {
672 impl_bundle_for_tuples!(@impl $($rev),*);
673 };
674
675 (@rev $head:ident $(,$tail:ident)*; $($rev:ident),*) => {
676 impl_bundle_for_tuples!(@rev $($tail),*; $head $(,$rev)*);
677 };
678
679 (@impl $($types:ident),*) => {
680 #[allow(unused_variables)]
681 unsafe impl<$($types),*> Bundle for ($($types,)*)
682 where
683 $($types: 'static,)*
684 {
685 fn contains<T>() -> bool
686 where
687 T: 'static
688 {
689 $(
690 if TypeId::of::<$types>() == TypeId::of::<T>() {
691 return true;
692 }
693 )*
694
695 false
696 }
697
698 fn insert(types: &mut TypeMetadataSet) {
699 $(
700 assert_ne!(
701 TypeId::of::<$types>(),
702 TypeId::of::<Entity>(),
703 "Entity cannot be inserted"
704 );
705
706 types.insert::<$types>();
707 )*
708 }
709
710 fn remove(types: &mut TypeMetadataSet) -> Option<()> {
711 $(
712 assert_ne!(
713 TypeId::of::<$types>(),
714 TypeId::of::<Entity>(),
715 "Entity cannot be removed"
716 );
717
718 types.remove::<$types>()?;
719 )*
720
721 Some(())
722 }
723
724 unsafe fn drop<T>(archetype: &mut Archetype, idx: u32)
725 where
726 T: Bundle
727 {
728 $(
729 if !T::contains::<$types>() {
730 archetype.drop::<$types>(idx);
731 }
732 )*
733 }
734
735 #[allow(non_snake_case)]
736 unsafe fn write(self, archetype: &mut Archetype, idx: u32) {
737 let ($($types,)*) = self;
738 $(archetype.get::<$types>(idx).write($types);)*
739 }
740
741 #[allow(non_snake_case)]
742 #[allow(clippy::unused_unit)]
743 unsafe fn read(archetype: &mut Archetype, idx: u32) -> Self {
744 $(let $types = archetype.get::<$types>(idx).read();)*
745 ($($types,)*)
746 }
747 }
748 };
749}
750
751impl_bundle_for_tuples!(J, I, H, G, F, E, D, C, B, A);
752
753type IndexTypeIdMap<V> = HashMap<(u16, TypeId), V, BuildHasherDefault<IndexTypeIdHasher>>;
754
755#[derive(Default)]
756struct IndexTypeIdHasher(u64);
757
758impl Hasher for IndexTypeIdHasher {
759 fn write_u16(&mut self, val: u16) {
760 self.0 = u64::from(val);
761 }
762
763 fn write_u64(&mut self, val: u64) {
764 self.0 ^= val;
765 }
766
767 fn write(&mut self, _val: &[u8]) {
768 unreachable!();
769 }
770
771 fn finish(&self) -> u64 {
772 self.0
773 }
774}
775
776type IndexTagMap<V> = HashMap<(u16, u32), V, BuildHasherDefault<IndexTagHasher>>;
777
778#[derive(Default)]
779struct IndexTagHasher(u64);
780
781impl Hasher for IndexTagHasher {
782 fn write_u16(&mut self, val: u16) {
783 self.0 = u64::from(val);
784 }
785
786 fn write_u32(&mut self, val: u32) {
787 self.0 |= u64::from(val) << 16;
788 }
789
790 fn write(&mut self, _val: &[u8]) {
791 unreachable!();
792 }
793
794 fn finish(&self) -> u64 {
795 self.0.wrapping_mul(0x517cc1b727220a95)
796 }
797}
798
799#[cfg(test)]
800mod tests {
801 use super::*;
802
803 use std::cell::Cell;
804 #[cfg(not(miri))]
805 use std::hash::Hash;
806 use std::mem::size_of;
807 use std::rc::Rc;
808
809 struct SetOnDrop(Rc<Cell<bool>>);
810
811 impl Drop for SetOnDrop {
812 fn drop(&mut self) {
813 self.0.set(true);
814 }
815 }
816
817 #[test]
818 fn alloc_creates_unique_entities() {
819 let mut world = World::new();
820
821 let ent1 = world.alloc();
822 let ent2 = world.alloc();
823
824 world.free(ent1);
825 let ent3 = world.alloc();
826
827 assert_ne!(ent1, ent2);
828 assert_ne!(ent2, ent3);
829
830 assert_eq!(ent3.id, ent1.id);
831 assert_ne!(ent3.gen, ent1.gen);
832 }
833
834 #[test]
835 #[should_panic]
836 fn freed_entities_cannot_be_accessed() {
837 let mut world = World::new();
838
839 let ent = world.alloc();
840 world.insert(ent, (42,));
841
842 world.query_one::<&i32>(ent).unwrap();
843
844 world.free(ent);
845
846 world.query_one::<&i32>(ent).unwrap();
847 }
848
849 #[test]
850 fn entity_metadata_is_updated_after_compacting_archetypes() {
851 let mut world = World::new();
852
853 let ent1 = world.alloc();
854 let _ent2 = world.alloc();
855 let _ent3 = world.alloc();
856
857 assert_eq!(world.entities.len(), 3);
858 assert_eq!(world.entities[0].idx, 0);
859 assert_eq!(world.entities[1].idx, 1);
860 assert_eq!(world.entities[2].idx, 2);
861
862 assert_eq!(world.free_list.len(), 0);
863
864 world.free(ent1);
865
866 assert_eq!(world.entities.len(), 3);
867 assert_eq!(world.entities[1].idx, 1);
868 assert_eq!(world.entities[2].idx, 0);
869
870 assert_eq!(world.free_list.len(), 1);
871 assert_eq!(world.free_list[0], 0);
872 }
873
874 #[test]
875 fn inserting_component_creates_archetype() {
876 let mut world = World::new();
877
878 assert_eq!(world.entities.len(), 0);
879
880 assert_eq!(world.archetypes.len(), 1);
881 assert_eq!(world.archetypes[0].len(), 0);
882
883 assert_eq!(world.exchange_map.len(), 0);
884
885 let ent = world.alloc();
886
887 assert_eq!(world.entities.len(), 1);
888 assert_eq!(world.entities[0].gen.get(), 1);
889 assert_eq!(world.entities[0].ty, 0);
890 assert_eq!(world.entities[0].idx, 0);
891
892 assert_eq!(world.archetypes.len(), 1);
893 assert_eq!(world.archetypes[0].len(), 1);
894
895 assert_eq!(world.exchange_map.len(), 0);
896
897 world.insert(ent, (23_i32,));
898
899 assert_eq!(world.entities.len(), 1);
900 assert_eq!(world.entities[0].gen.get(), 1);
901 assert_eq!(world.entities[0].ty, 1);
902 assert_eq!(world.entities[0].idx, 0);
903
904 assert_eq!(world.archetypes.len(), 2);
905 assert_eq!(world.archetypes[0].len(), 0);
906 assert_eq!(world.archetypes[1].len(), 1);
907
908 assert_eq!(world.exchange_map.len(), 1);
909 assert_eq!(world.exchange_map[&(0, TypeId::of::<((), (i32,))>())], 1);
910 }
911
912 #[test]
913 fn removing_component_creates_archetype() {
914 let mut world = World::new();
915
916 assert_eq!(world.entities.len(), 0);
917
918 assert_eq!(world.archetypes.len(), 1);
919 assert_eq!(world.archetypes[0].len(), 0);
920
921 assert_eq!(world.exchange_map.len(), 0);
922
923 let ent = world.alloc();
924
925 world.insert(ent, (23_i32, 42_u64));
926
927 assert_eq!(world.entities.len(), 1);
928 assert_eq!(world.entities[0].gen.get(), 1);
929 assert_eq!(world.entities[0].ty, 1);
930 assert_eq!(world.entities[0].idx, 0);
931
932 assert_eq!(world.archetypes.len(), 2);
933 assert_eq!(world.archetypes[0].len(), 0);
934 assert_eq!(world.archetypes[1].len(), 1);
935
936 assert_eq!(world.exchange_map.len(), 1);
937 assert_eq!(
938 world.exchange_map[&(0, TypeId::of::<((), (i32, u64))>())],
939 1
940 );
941
942 world.remove::<(i32,)>(ent).unwrap();
943
944 assert_eq!(world.entities.len(), 1);
945 assert_eq!(world.entities[0].gen.get(), 1);
946 assert_eq!(world.entities[0].ty, 2);
947 assert_eq!(world.entities[0].idx, 0);
948
949 assert_eq!(world.archetypes.len(), 3);
950 assert_eq!(world.archetypes[0].len(), 0);
951 assert_eq!(world.archetypes[1].len(), 0);
952 assert_eq!(world.archetypes[2].len(), 1);
953
954 assert_eq!(world.exchange_map.len(), 2);
955 assert_eq!(
956 world.exchange_map[&(0, TypeId::of::<((), (i32, u64))>())],
957 1
958 );
959 assert_eq!(world.exchange_map[&(1, TypeId::of::<((i32,), ())>())], 2);
960 }
961
962 #[test]
963 fn insert_can_be_used_to_overwrite_components() {
964 let drop1 = Rc::new(Cell::new(false));
965 let drop2 = Rc::new(Cell::new(false));
966 let drop3 = Rc::new(Cell::new(false));
967
968 let mut world = World::new();
969
970 let entity1 = world.alloc();
971 world.insert(entity1, (0, SetOnDrop(drop1.clone())));
972
973 let entity2 = world.alloc();
974
975 world.insert(entity1, (1, SetOnDrop(drop2.clone())));
976 world.insert(entity2, (2, SetOnDrop(drop3.clone())));
977
978 assert_eq!(*world.query_one::<&i32>(entity1).unwrap().get(), 1);
979 assert_eq!(*world.query_one::<&i32>(entity2).unwrap().get(), 2);
980
981 assert_eq!(world.exchange_map.len(), 2);
982 assert_eq!(
983 world.exchange_map[&(0, TypeId::of::<((), (i32, SetOnDrop))>())],
984 1
985 );
986 assert_eq!(
987 world.exchange_map[&(1, TypeId::of::<((), (i32, SetOnDrop))>())],
988 1
989 );
990
991 assert!(drop1.get());
992 assert!(!drop2.get());
993 assert!(!drop3.get());
994 }
995
996 #[test]
997 fn exchange_can_be_used_to_overwrite_components() {
998 let drop1 = Rc::new(Cell::new(false));
999 let drop2 = Rc::new(Cell::new(false));
1000
1001 let mut world = World::new();
1002
1003 let entity = world.alloc();
1004 world.insert(entity, (0, true, SetOnDrop(drop1.clone())));
1005 world
1006 .exchange::<(bool,), _>(entity, (1, SetOnDrop(drop2.clone())))
1007 .unwrap();
1008
1009 assert_eq!(*world.query_one::<&i32>(entity).unwrap().get(), 1);
1010 assert!(!world.contains::<bool>(entity));
1011
1012 assert_eq!(world.exchange_map.len(), 2);
1013 assert_eq!(
1014 world.exchange_map[&(0, TypeId::of::<((), (i32, bool, SetOnDrop))>())],
1015 1
1016 );
1017 assert_eq!(
1018 world.exchange_map[&(1, TypeId::of::<((bool,), (i32, SetOnDrop))>())],
1019 2
1020 );
1021
1022 assert!(drop1.get());
1023 assert!(!drop2.get());
1024 }
1025
1026 #[test]
1027 #[allow(clippy::let_unit_value)]
1028 fn empty_remove_is_essentially_a_noop() {
1029 let mut world = World::new();
1030
1031 let ent = world.alloc();
1032 world.insert(ent, (true,));
1033
1034 let () = world.remove::<()>(ent).unwrap();
1035 }
1036
1037 #[test]
1038 fn trival_exchange_does_not_create_aliasing_unique_references() {
1039 let mut world = World::new();
1040
1041 let ent = world.alloc();
1042 world.insert(ent, (true,));
1043
1044 world.exchange::<(bool,), _>(ent, (false,)).unwrap();
1045
1046 assert_eq!(world.exchange_map.len(), 2);
1047 assert_eq!(world.exchange_map[&(0, TypeId::of::<((), (bool,))>())], 1);
1048 assert_eq!(
1049 world.exchange_map[&(1, TypeId::of::<((bool,), (bool,))>())],
1050 1
1051 );
1052 }
1053
1054 #[test]
1055 fn insert_then_get() {
1056 let mut world = World::new();
1057
1058 let ent = world.alloc();
1059 world.insert(ent, (23,));
1060
1061 let comp = world.query_one::<&i32>(ent).unwrap();
1062 assert_eq!(*comp.get(), 23);
1063 }
1064
1065 #[test]
1066 fn get_mut_then_get() {
1067 let mut world = World::new();
1068
1069 let ent = world.alloc();
1070 world.insert(ent, (23,));
1071
1072 {
1073 let mut comp = world.query_one::<&mut i32>(ent).unwrap();
1074 *comp.get_mut() = 42;
1075 }
1076
1077 let comp = world.query_one::<&i32>(ent).unwrap();
1078 assert_eq!(*comp.get(), 42);
1079 }
1080
1081 #[test]
1082 fn borrows_can_be_shared() {
1083 let mut world = World::new();
1084
1085 let ent = world.alloc();
1086 world.insert(ent, ((),));
1087
1088 let _comp = world.query_one::<&()>(ent).unwrap();
1089 let _comp = world.query_one::<&()>(ent).unwrap();
1090 }
1091
1092 #[test]
1093 #[should_panic]
1094 fn mutable_borrows_are_exclusive() {
1095 let mut world = World::new();
1096
1097 let ent = world.alloc();
1098 world.insert(ent, ((),));
1099
1100 let _comp = world.query_one::<&mut ()>(ent).unwrap();
1101 let _comp = world.query_one::<&mut ()>(ent).unwrap();
1102 }
1103
1104 #[test]
1105 fn entity_id_are_consistent() {
1106 let mut world = World::new();
1107
1108 let ent1 = world.alloc();
1109 let ent2 = world.alloc();
1110 world.free(ent1);
1111 let ent3 = world.alloc();
1112
1113 assert_eq!(*world.query_one::<&Entity>(ent2).unwrap().get(), ent2);
1114 assert_eq!(*world.query_one::<&Entity>(ent3).unwrap().get(), ent3);
1115 }
1116
1117 #[test]
1118 #[should_panic]
1119 fn entity_id_cannot_be_modified() {
1120 let mut world = World::new();
1121
1122 let ent = world.alloc();
1123 let _ = world.query_one::<&mut Entity>(ent);
1124 }
1125
1126 #[test]
1127 #[should_panic]
1128 fn entity_id_cannot_be_removed() {
1129 let mut world = World::new();
1130
1131 let ent = world.alloc();
1132 let _ = world.remove::<(Entity,)>(ent);
1133 }
1134
1135 #[test]
1136 fn entity_has_niche() {
1137 assert_eq!(size_of::<Entity>(), size_of::<Option<Entity>>());
1138 }
1139
1140 #[test]
1141 fn world_can_be_cleared() {
1142 let mut world = World::new();
1143
1144 let ent1 = world.alloc();
1145 world.insert(ent1, (23,));
1146
1147 let ent2 = world.alloc();
1148 world.free(ent2);
1149
1150 assert_eq!(world.entities.len(), 2);
1151 assert_eq!(world.free_list.len(), 1);
1152
1153 assert_eq!(world.archetypes.len(), 2);
1154 assert_eq!(world.archetypes[0].len(), 0);
1155 assert_eq!(world.archetypes[1].len(), 1);
1156
1157 world.clear();
1158
1159 assert_eq!(world.entities.len(), 0);
1160 assert_eq!(world.free_list.len(), 0);
1161
1162 assert_eq!(world.archetypes.len(), 2);
1163 assert_eq!(world.archetypes[0].len(), 0);
1164 assert_eq!(world.archetypes[1].len(), 0);
1165 }
1166
1167 #[test]
1168 fn clearing_the_world_repeats_entities() {
1169 let mut world = World::new();
1170
1171 let ent = world.alloc();
1172 assert_eq!(ent.id, 0);
1173 assert_eq!(world.entities.len(), 1);
1174 assert_eq!(world.entities[0].gen.get(), 1);
1175
1176 world.clear();
1177
1178 let ent = world.alloc();
1179 assert_eq!(ent.id, 0);
1180 assert_eq!(world.entities.len(), 1);
1181 assert_eq!(world.entities[0].gen.get(), 1);
1182 }
1183
1184 #[test]
1185 fn entities_can_be_transferred_between_worlds() {
1186 let mut world1 = World::new();
1187
1188 let ent1 = world1.alloc();
1189 world1.insert(ent1, (23, true, 42.0));
1190 world1.remove::<(bool,)>(ent1);
1191
1192 let mut world2 = World::new();
1193
1194 let ent2 = world1.transfer(ent1, &mut world2);
1195
1196 assert_eq!(*world1.transfer_map.get(&(2, world2.tag)).unwrap(), 1);
1197 assert_eq!(*world2.transfer_map.get(&(1, world1.tag)).unwrap(), 2);
1198
1199 assert!(!world1.exists(ent1));
1200 assert!(world2.exists(ent2));
1201
1202 let comp = world2.query_one::<&i32>(ent2).unwrap();
1203 assert_eq!(*comp.get(), 23);
1204 }
1205
1206 #[test]
1207 fn worlds_can_be_cloned() {
1208 let mut world1 = World::new();
1209
1210 let ent = world1.alloc();
1211 world1.insert(ent, (23, true, 42.0));
1212 world1.insert(ent, ("foobar".to_owned(),));
1213
1214 let mut cloner = Cloner::new();
1215
1216 cloner.add_copyable::<i32>();
1217 cloner.add_copyable::<bool>();
1218 cloner.add_copyable::<f64>();
1219 cloner.add_cloneable::<String>();
1220
1221 let world2 = world1.clone(&cloner);
1222
1223 assert!(world1.exists(ent));
1224 assert!(world2.exists(ent));
1225
1226 let comp = world2.query_one::<&String>(ent).unwrap();
1227 assert_eq!(*comp.get(), "foobar");
1228 }
1229
1230 #[cfg(not(miri))]
1231 #[test]
1232 fn index_type_id_yields_uniformly_distributed_lower_bits() {
1233 let mut histogram = [0; 128];
1234
1235 for i in 0_u16..1024 {
1236 for t in [
1237 TypeId::of::<(i32,)>(),
1238 TypeId::of::<(bool, f32)>(),
1239 TypeId::of::<(i32, &str)>(),
1240 TypeId::of::<(bool, &str, f64)>(),
1241 ] {
1242 let mut hasher = IndexTypeIdHasher::default();
1243 (i, t).hash(&mut hasher);
1244 let hash = hasher.finish();
1245
1246 histogram[hash as usize % histogram.len()] += 1;
1247 }
1248 }
1249
1250 for count in histogram {
1251 assert_eq!(count, 1024 * 4 / histogram.len());
1252 }
1253 }
1254
1255 #[cfg(not(miri))]
1256 #[test]
1257 fn index_tag_hasher_yields_uniformly_distributed_lower_bits() {
1258 let mut histogram = [0; 128];
1259
1260 for i in 0_u16..1024 {
1261 for j in 0_u32..128 {
1262 let mut hasher = IndexTagHasher::default();
1263 (i, j).hash(&mut hasher);
1264 let hash = hasher.finish();
1265
1266 histogram[hash as usize % histogram.len()] += 1;
1267 }
1268 }
1269
1270 for count in histogram {
1271 assert_eq!(count, 1024 * 128 / histogram.len());
1272 }
1273 }
1274}