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