1use std::any::TypeId;
2use std::collections::HashMap;
3use std::convert::TryInto;
4use std::hash::{BuildHasherDefault, Hasher};
5use std::mem::{transmute_copy, ManuallyDrop};
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 struct MoveOnDrop<'a, B2>
262 where
263 B2: Bundle,
264 {
265 world: &'a mut World,
266 ent_id: u32,
267 old_ty: u16,
268 new_ty: u16,
269 old_idx: u32,
270 new_comps: ManuallyDrop<B2>,
271 }
272
273 impl<B2> Drop for MoveOnDrop<'_, B2>
274 where
275 B2: Bundle,
276 {
277 fn drop(&mut self) {
278 unsafe {
279 let new_idx =
280 self.world
281 .move_(self.ent_id, self.old_ty, self.new_ty, self.old_idx);
282
283 let new_archetype = &mut self.world.archetypes[self.new_ty as usize];
284 ManuallyDrop::take(&mut self.new_comps).write(new_archetype, new_idx);
285 }
286 }
287 }
288
289 let guard = MoveOnDrop {
290 world: self,
291 ent_id: ent.id,
292 old_ty,
293 new_ty,
294 old_idx,
295 new_comps: ManuallyDrop::new(new_comps),
296 };
297
298 let old_archetype = &mut guard.world.archetypes[old_ty as usize];
299 let old_comps = B1::read(old_archetype, old_idx);
300 B2::drop::<B1>(old_archetype, old_idx);
301
302 Some(old_comps)
303 }
304 }
305
306 #[cold]
307 #[inline(never)]
308 fn exchange_cold(
309 archetypes: &mut Vec<Archetype>,
310 borrow_flags: &mut BorrowFlags,
311 exchange_map: &mut IndexTypeIdMap<u16>,
312 key: TypeId,
313 remove: fn(&mut TypeMetadataSet) -> Option<()>,
314 insert: fn(&mut TypeMetadataSet),
315 old_ty: u16,
316 ) -> Option<u16> {
317 let mut types = archetypes[old_ty as usize].types();
318 remove(&mut types)?;
319 insert(&mut types);
320
321 let new_ty = Self::get_or_insert(archetypes, borrow_flags, types);
322
323 exchange_map.insert((old_ty, key), new_ty);
324
325 Some(new_ty)
326 }
327
328 fn get_or_insert(
329 archetypes: &mut Vec<Archetype>,
330 borrow_flags: &mut BorrowFlags,
331 types: TypeMetadataSet,
332 ) -> u16 {
333 let pos = archetypes
334 .iter()
335 .position(|archetype| archetype.match_(&types));
336
337 if let Some(pos) = pos {
338 pos as u16
339 } else {
340 let len = archetypes.len();
341 assert!(len < u16::MAX as usize);
342
343 borrow_flags.insert(&types);
344
345 archetypes.push(Archetype::new(types));
346
347 len as u16
348 }
349 }
350
351 unsafe fn move_(&mut self, id: u32, old_ty: u16, new_ty: u16, old_idx: u32) -> u32 {
352 if old_ty == new_ty {
353 return old_idx;
354 }
355
356 debug_assert!(self.archetypes.len() > old_ty as usize);
357 debug_assert!(self.archetypes.len() > new_ty as usize);
358
359 let archetypes = self.archetypes.as_mut_ptr();
360 let old_archetype = &mut *archetypes.add(old_ty as usize);
361 let new_archetype = &mut *archetypes.add(new_ty as usize);
362
363 let new_idx = new_archetype.alloc();
364
365 Archetype::move_(old_archetype, new_archetype, old_idx, new_idx);
366
367 Self::free_idx::<false>(old_archetype, old_idx, &mut self.entities);
368
369 let meta = &mut self.entities[id as usize];
370 meta.ty = new_ty;
371 meta.idx = new_idx;
372
373 new_idx
374 }
375}
376
377impl World {
378 pub fn transfer(&mut self, ent: Entity, other: &mut World) -> Entity {
396 let meta = &mut self.entities[ent.id as usize];
397 assert_eq!(ent.gen, meta.gen, "Entity is stale");
398
399 let new_id = other.alloc_id();
401
402 let new_meta = &mut other.entities[new_id as usize];
403
404 meta.bump_gen();
406
407 self.free_list.push(ent.id);
408
409 new_meta.ty = if let Some(ty) = self.transfer_map.get(&(meta.ty, other.tag)) {
411 *ty
412 } else {
413 Self::transfer_cold(
414 &self.archetypes,
415 &mut other.archetypes,
416 &mut other.borrow_flags,
417 &mut self.transfer_map,
418 &mut other.transfer_map,
419 self.tag,
420 other.tag,
421 meta.ty,
422 )
423 };
424
425 let old_archetype = &mut self.archetypes[meta.ty as usize];
427 let new_archetype = &mut other.archetypes[new_meta.ty as usize];
428
429 unsafe {
430 new_meta.idx = new_archetype.alloc();
431
432 Archetype::move_(old_archetype, new_archetype, meta.idx, new_meta.idx);
433
434 Self::free_idx::<false>(old_archetype, meta.idx, &mut self.entities);
435 }
436
437 let ent = Entity {
439 id: new_id,
440 gen: new_meta.gen,
441 };
442
443 unsafe {
444 new_archetype.get::<Entity>(new_meta.idx).write(ent);
445 }
446
447 ent
448 }
449
450 #[allow(clippy::too_many_arguments)]
451 #[cold]
452 #[inline(never)]
453 fn transfer_cold(
454 archetypes: &[Archetype],
455 other_archetypes: &mut Vec<Archetype>,
456 other_borrows: &mut BorrowFlags,
457 transfer_map: &mut IndexTagMap<u16>,
458 other_transfer_map: &mut IndexTagMap<u16>,
459 tag: u32,
460 other_tag: u32,
461 old_ty: u16,
462 ) -> u16 {
463 let types = archetypes[old_ty as usize].types();
464
465 let new_ty = Self::get_or_insert(other_archetypes, other_borrows, types);
466
467 transfer_map.insert((old_ty, other_tag), new_ty);
468 other_transfer_map.insert((new_ty, tag), old_ty);
469
470 new_ty
471 }
472}
473
474impl World {
475 pub fn exists(&self, ent: Entity) -> bool {
490 let meta = &self.entities[ent.id as usize];
491 ent.gen == meta.gen
492 }
493
494 pub fn contains<C>(&self, ent: Entity) -> bool
508 where
509 C: 'static,
510 {
511 let meta = &self.entities[ent.id as usize];
512 assert_eq!(ent.gen, meta.gen, "Entity is stale");
513
514 self.archetypes[meta.ty as usize].find::<C>().is_some()
515 }
516
517 pub fn query_one<S>(&self, ent: Entity) -> Option<QueryOne<'_, S>>
539 where
540 S: QuerySpec,
541 {
542 let meta = &self.entities[ent.id as usize];
543 assert_eq!(ent.gen, meta.gen, "Entity is stale");
544
545 let flags = S::Fetch::find_flags(&self.borrow_flags)?;
546 let _ref = unsafe { S::Fetch::borrow(&self.borrow_flags, flags) };
547
548 let archetype = &self.archetypes[meta.ty as usize];
549
550 let comps = S::Fetch::find_comps(archetype)?;
551 let ptr = unsafe { S::Fetch::base_pointer(archetype, comps) };
552
553 Some(QueryOne {
554 _ref,
555 ptr,
556 idx: meta.idx,
557 })
558 }
559}
560
561impl World {
562 pub fn clone(&mut self, cloner: &Cloner) -> Self {
589 let archetypes = self
590 .archetypes
591 .iter_mut()
592 .map(|archetype| archetype.clone(cloner))
593 .collect();
594
595 Self {
596 tag: tag(),
597 entities: self.entities.clone(),
598 free_list: self.free_list.clone(),
599 borrow_flags: self.borrow_flags.clone(),
600 archetypes,
601 exchange_map: self.exchange_map.clone(),
602 transfer_map: self.transfer_map.clone(),
603 }
604 }
605}
606
607#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
609pub struct Entity {
610 pub(crate) id: u32,
611 pub(crate) gen: NonZeroU32,
612}
613
614#[derive(Clone, Copy)]
615pub struct EntityMetadata {
616 pub gen: NonZeroU32,
617 pub ty: u16,
618 pub idx: u32,
619}
620
621impl Default for EntityMetadata {
622 fn default() -> Self {
623 Self {
624 gen: unsafe { NonZeroU32::new_unchecked(1) },
625 ty: 0,
626 idx: 0,
627 }
628 }
629}
630
631impl EntityMetadata {
632 fn bump_gen(&mut self) {
633 let gen = self.gen.get();
634
635 if gen == u32::MAX {
636 abort();
637 }
638
639 self.gen = unsafe { NonZeroU32::new_unchecked(gen + 1) };
640 }
641}
642
643pub struct QueryOne<'w, S>
645where
646 S: QuerySpec,
647{
648 _ref: <S::Fetch as Fetch<'w>>::Ref,
649 ptr: <S::Fetch as Fetch<'w>>::Ptr,
650 idx: u32,
651}
652
653impl<S> QueryOne<'_, S>
654where
655 S: QuerySpec,
656{
657 pub fn get(&self) -> <S::Fetch as Fetch<'_>>::Item
661 where
662 S::Fetch: FetchShared,
663 {
664 unsafe { S::Fetch::deref(transmute_copy(&self.ptr), self.idx) }
665 }
666
667 pub fn get_mut(&mut self) -> <S::Fetch as Fetch<'_>>::Item {
669 unsafe { S::Fetch::deref(transmute_copy(&self.ptr), self.idx) }
670 }
671}
672
673#[allow(clippy::missing_safety_doc)]
674pub unsafe trait Bundle
675where
676 Self: 'static,
677{
678 fn contains<T>() -> bool
679 where
680 T: 'static;
681
682 fn insert(types: &mut TypeMetadataSet);
683 #[must_use]
684 fn remove(types: &mut TypeMetadataSet) -> Option<()>;
685
686 unsafe fn drop<T>(archetype: &mut Archetype, idx: u32)
687 where
688 T: Bundle;
689
690 unsafe fn write(self, archetype: &mut Archetype, idx: u32);
691 unsafe fn read(archetype: &mut Archetype, idx: u32) -> Self;
692}
693
694macro_rules! impl_bundle_for_tuples {
695 () => {
696 impl_bundle_for_tuples!(@impl);
697 };
698
699 ($head:ident $(,$tail:ident)*) => {
700 impl_bundle_for_tuples!($($tail),*);
701 impl_bundle_for_tuples!(@rev $head $(,$tail)*;);
702 };
703
704 (@rev ; $($rev:ident),*) => {
705 impl_bundle_for_tuples!(@impl $($rev),*);
706 };
707
708 (@rev $head:ident $(,$tail:ident)*; $($rev:ident),*) => {
709 impl_bundle_for_tuples!(@rev $($tail),*; $head $(,$rev)*);
710 };
711
712 (@impl $($types:ident),*) => {
713 #[allow(unused_variables)]
714 unsafe impl<$($types),*> Bundle for ($($types,)*)
715 where
716 $($types: 'static,)*
717 {
718 fn contains<T>() -> bool
719 where
720 T: 'static
721 {
722 $(
723 if TypeId::of::<$types>() == TypeId::of::<T>() {
724 return true;
725 }
726 )*
727
728 false
729 }
730
731 fn insert(types: &mut TypeMetadataSet) {
732 $(
733 assert_ne!(
734 TypeId::of::<$types>(),
735 TypeId::of::<Entity>(),
736 "Entity cannot be inserted"
737 );
738
739 types.insert::<$types>();
740 )*
741 }
742
743 fn remove(types: &mut TypeMetadataSet) -> Option<()> {
744 $(
745 assert_ne!(
746 TypeId::of::<$types>(),
747 TypeId::of::<Entity>(),
748 "Entity cannot be removed"
749 );
750
751 types.remove::<$types>()?;
752 )*
753
754 Some(())
755 }
756
757 unsafe fn drop<T>(archetype: &mut Archetype, idx: u32)
758 where
759 T: Bundle
760 {
761 $(
762 if !T::contains::<$types>() {
763 archetype.drop::<$types>(idx);
764 }
765 )*
766 }
767
768 #[allow(non_snake_case)]
769 unsafe fn write(self, archetype: &mut Archetype, idx: u32) {
770 let ($($types,)*) = self;
771 $(archetype.get::<$types>(idx).write($types);)*
772 }
773
774 #[allow(non_snake_case)]
775 #[allow(clippy::unused_unit)]
776 unsafe fn read(archetype: &mut Archetype, idx: u32) -> Self {
777 $(let $types = archetype.get::<$types>(idx).read();)*
778 ($($types,)*)
779 }
780 }
781 };
782}
783
784impl_bundle_for_tuples!(J, I, H, G, F, E, D, C, B, A);
785
786type IndexTypeIdMap<V> = HashMap<(u16, TypeId), V, BuildHasherDefault<IndexTypeIdHasher>>;
787
788#[derive(Default)]
789struct IndexTypeIdHasher(u64);
790
791impl Hasher for IndexTypeIdHasher {
792 fn write_u16(&mut self, val: u16) {
793 self.0 = u64::from(val);
794 }
795
796 fn write_u64(&mut self, val: u64) {
797 self.0 ^= val;
798 }
799
800 fn write(&mut self, _val: &[u8]) {
801 unreachable!();
802 }
803
804 fn finish(&self) -> u64 {
805 self.0
806 }
807}
808
809type IndexTagMap<V> = HashMap<(u16, u32), V, BuildHasherDefault<IndexTagHasher>>;
810
811#[derive(Default)]
812struct IndexTagHasher(u64);
813
814impl Hasher for IndexTagHasher {
815 fn write_u16(&mut self, val: u16) {
816 self.0 = u64::from(val);
817 }
818
819 fn write_u32(&mut self, val: u32) {
820 self.0 |= u64::from(val) << 16;
821 }
822
823 fn write(&mut self, _val: &[u8]) {
824 unreachable!();
825 }
826
827 fn finish(&self) -> u64 {
828 self.0.wrapping_mul(0x517cc1b727220a95)
829 }
830}
831
832#[cfg(test)]
833mod tests {
834 use super::*;
835
836 use std::cell::Cell;
837 #[cfg(not(miri))]
838 use std::hash::Hash;
839 use std::mem::size_of;
840 use std::panic::{catch_unwind, AssertUnwindSafe};
841 use std::rc::Rc;
842 use std::thread::panicking;
843
844 struct SetOnDrop(Rc<Cell<bool>>);
845
846 impl Drop for SetOnDrop {
847 fn drop(&mut self) {
848 self.0.set(true);
849 }
850 }
851
852 struct MaybePanicOnDrop(bool);
853
854 impl Drop for MaybePanicOnDrop {
855 fn drop(&mut self) {
856 if self.0 && !panicking() {
857 panic!();
858 }
859 }
860 }
861
862 #[test]
863 fn alloc_creates_unique_entities() {
864 let mut world = World::new();
865
866 let ent1 = world.alloc();
867 let ent2 = world.alloc();
868
869 world.free(ent1);
870 let ent3 = world.alloc();
871
872 assert_ne!(ent1, ent2);
873 assert_ne!(ent2, ent3);
874
875 assert_eq!(ent3.id, ent1.id);
876 assert_ne!(ent3.gen, ent1.gen);
877 }
878
879 #[test]
880 #[should_panic]
881 fn freed_entities_cannot_be_accessed() {
882 let mut world = World::new();
883
884 let ent = world.alloc();
885 world.insert(ent, (42,));
886
887 world.query_one::<&i32>(ent).unwrap();
888
889 world.free(ent);
890
891 world.query_one::<&i32>(ent).unwrap();
892 }
893
894 #[test]
895 fn entity_metadata_is_updated_after_compacting_archetypes() {
896 let mut world = World::new();
897
898 let ent1 = world.alloc();
899 let _ent2 = world.alloc();
900 let _ent3 = world.alloc();
901
902 assert_eq!(world.entities.len(), 3);
903 assert_eq!(world.entities[0].idx, 0);
904 assert_eq!(world.entities[1].idx, 1);
905 assert_eq!(world.entities[2].idx, 2);
906
907 assert_eq!(world.free_list.len(), 0);
908
909 world.free(ent1);
910
911 assert_eq!(world.entities.len(), 3);
912 assert_eq!(world.entities[1].idx, 1);
913 assert_eq!(world.entities[2].idx, 0);
914
915 assert_eq!(world.free_list.len(), 1);
916 assert_eq!(world.free_list[0], 0);
917 }
918
919 #[test]
920 fn inserting_component_creates_archetype() {
921 let mut world = World::new();
922
923 assert_eq!(world.entities.len(), 0);
924
925 assert_eq!(world.archetypes.len(), 1);
926 assert_eq!(world.archetypes[0].len(), 0);
927
928 assert_eq!(world.exchange_map.len(), 0);
929
930 let ent = world.alloc();
931
932 assert_eq!(world.entities.len(), 1);
933 assert_eq!(world.entities[0].gen.get(), 1);
934 assert_eq!(world.entities[0].ty, 0);
935 assert_eq!(world.entities[0].idx, 0);
936
937 assert_eq!(world.archetypes.len(), 1);
938 assert_eq!(world.archetypes[0].len(), 1);
939
940 assert_eq!(world.exchange_map.len(), 0);
941
942 world.insert(ent, (23_i32,));
943
944 assert_eq!(world.entities.len(), 1);
945 assert_eq!(world.entities[0].gen.get(), 1);
946 assert_eq!(world.entities[0].ty, 1);
947 assert_eq!(world.entities[0].idx, 0);
948
949 assert_eq!(world.archetypes.len(), 2);
950 assert_eq!(world.archetypes[0].len(), 0);
951 assert_eq!(world.archetypes[1].len(), 1);
952
953 assert_eq!(world.exchange_map.len(), 1);
954 assert_eq!(world.exchange_map[&(0, TypeId::of::<((), (i32,))>())], 1);
955 }
956
957 #[test]
958 fn removing_component_creates_archetype() {
959 let mut world = World::new();
960
961 assert_eq!(world.entities.len(), 0);
962
963 assert_eq!(world.archetypes.len(), 1);
964 assert_eq!(world.archetypes[0].len(), 0);
965
966 assert_eq!(world.exchange_map.len(), 0);
967
968 let ent = world.alloc();
969
970 world.insert(ent, (23_i32, 42_u64));
971
972 assert_eq!(world.entities.len(), 1);
973 assert_eq!(world.entities[0].gen.get(), 1);
974 assert_eq!(world.entities[0].ty, 1);
975 assert_eq!(world.entities[0].idx, 0);
976
977 assert_eq!(world.archetypes.len(), 2);
978 assert_eq!(world.archetypes[0].len(), 0);
979 assert_eq!(world.archetypes[1].len(), 1);
980
981 assert_eq!(world.exchange_map.len(), 1);
982 assert_eq!(
983 world.exchange_map[&(0, TypeId::of::<((), (i32, u64))>())],
984 1
985 );
986
987 world.remove::<(i32,)>(ent).unwrap();
988
989 assert_eq!(world.entities.len(), 1);
990 assert_eq!(world.entities[0].gen.get(), 1);
991 assert_eq!(world.entities[0].ty, 2);
992 assert_eq!(world.entities[0].idx, 0);
993
994 assert_eq!(world.archetypes.len(), 3);
995 assert_eq!(world.archetypes[0].len(), 0);
996 assert_eq!(world.archetypes[1].len(), 0);
997 assert_eq!(world.archetypes[2].len(), 1);
998
999 assert_eq!(world.exchange_map.len(), 2);
1000 assert_eq!(
1001 world.exchange_map[&(0, TypeId::of::<((), (i32, u64))>())],
1002 1
1003 );
1004 assert_eq!(world.exchange_map[&(1, TypeId::of::<((i32,), ())>())], 2);
1005 }
1006
1007 #[test]
1008 fn insert_can_be_used_to_overwrite_components() {
1009 let drop1 = Rc::new(Cell::new(false));
1010 let drop2 = Rc::new(Cell::new(false));
1011 let drop3 = Rc::new(Cell::new(false));
1012
1013 let mut world = World::new();
1014
1015 let entity1 = world.alloc();
1016 world.insert(entity1, (0, SetOnDrop(drop1.clone())));
1017
1018 let entity2 = world.alloc();
1019
1020 world.insert(entity1, (1, SetOnDrop(drop2.clone())));
1021 world.insert(entity2, (2, SetOnDrop(drop3.clone())));
1022
1023 assert_eq!(*world.query_one::<&i32>(entity1).unwrap().get(), 1);
1024 assert_eq!(*world.query_one::<&i32>(entity2).unwrap().get(), 2);
1025
1026 assert_eq!(world.exchange_map.len(), 2);
1027 assert_eq!(
1028 world.exchange_map[&(0, TypeId::of::<((), (i32, SetOnDrop))>())],
1029 1
1030 );
1031 assert_eq!(
1032 world.exchange_map[&(1, TypeId::of::<((), (i32, SetOnDrop))>())],
1033 1
1034 );
1035
1036 assert!(drop1.get());
1037 assert!(!drop2.get());
1038 assert!(!drop3.get());
1039 }
1040
1041 #[test]
1042 fn exchange_can_be_used_to_overwrite_components() {
1043 let drop1 = Rc::new(Cell::new(false));
1044 let drop2 = Rc::new(Cell::new(false));
1045
1046 let mut world = World::new();
1047
1048 let entity = world.alloc();
1049 world.insert(entity, (0, true, SetOnDrop(drop1.clone())));
1050 world
1051 .exchange::<(bool,), _>(entity, (1, SetOnDrop(drop2.clone())))
1052 .unwrap();
1053
1054 assert_eq!(*world.query_one::<&i32>(entity).unwrap().get(), 1);
1055 assert!(!world.contains::<bool>(entity));
1056
1057 assert_eq!(world.exchange_map.len(), 2);
1058 assert_eq!(
1059 world.exchange_map[&(0, TypeId::of::<((), (i32, bool, SetOnDrop))>())],
1060 1
1061 );
1062 assert_eq!(
1063 world.exchange_map[&(1, TypeId::of::<((bool,), (i32, SetOnDrop))>())],
1064 2
1065 );
1066
1067 assert!(drop1.get());
1068 assert!(!drop2.get());
1069 }
1070
1071 #[test]
1072 fn insert_does_not_double_drop_on_panic() {
1073 let mut world = World::new();
1074
1075 let entity = world.alloc();
1076 world.insert(entity, (MaybePanicOnDrop(true),));
1077
1078 let res = catch_unwind(AssertUnwindSafe(|| {
1079 world.insert(entity, (MaybePanicOnDrop(false),));
1080 }));
1081 assert!(res.is_err());
1082
1083 let comp = world.query_one::<&MaybePanicOnDrop>(entity).unwrap();
1084 assert!(!comp.get().0);
1085 }
1086
1087 #[test]
1088 #[allow(clippy::let_unit_value)]
1089 fn empty_remove_is_essentially_a_noop() {
1090 let mut world = World::new();
1091
1092 let ent = world.alloc();
1093 world.insert(ent, (true,));
1094
1095 let () = world.remove::<()>(ent).unwrap();
1096 }
1097
1098 #[test]
1099 fn trival_exchange_does_not_create_aliasing_unique_references() {
1100 let mut world = World::new();
1101
1102 let ent = world.alloc();
1103 world.insert(ent, (true,));
1104
1105 world.exchange::<(bool,), _>(ent, (false,)).unwrap();
1106
1107 assert_eq!(world.exchange_map.len(), 2);
1108 assert_eq!(world.exchange_map[&(0, TypeId::of::<((), (bool,))>())], 1);
1109 assert_eq!(
1110 world.exchange_map[&(1, TypeId::of::<((bool,), (bool,))>())],
1111 1
1112 );
1113 }
1114
1115 #[test]
1116 fn insert_then_get() {
1117 let mut world = World::new();
1118
1119 let ent = world.alloc();
1120 world.insert(ent, (23,));
1121
1122 let comp = world.query_one::<&i32>(ent).unwrap();
1123 assert_eq!(*comp.get(), 23);
1124 }
1125
1126 #[test]
1127 fn get_mut_then_get() {
1128 let mut world = World::new();
1129
1130 let ent = world.alloc();
1131 world.insert(ent, (23,));
1132
1133 {
1134 let mut comp = world.query_one::<&mut i32>(ent).unwrap();
1135 *comp.get_mut() = 42;
1136 }
1137
1138 let comp = world.query_one::<&i32>(ent).unwrap();
1139 assert_eq!(*comp.get(), 42);
1140 }
1141
1142 #[test]
1143 fn borrows_can_be_shared() {
1144 let mut world = World::new();
1145
1146 let ent = world.alloc();
1147 world.insert(ent, ((),));
1148
1149 let _comp = world.query_one::<&()>(ent).unwrap();
1150 let _comp = world.query_one::<&()>(ent).unwrap();
1151 }
1152
1153 #[test]
1154 #[should_panic]
1155 fn mutable_borrows_are_exclusive() {
1156 let mut world = World::new();
1157
1158 let ent = world.alloc();
1159 world.insert(ent, ((),));
1160
1161 let _comp = world.query_one::<&mut ()>(ent).unwrap();
1162 let _comp = world.query_one::<&mut ()>(ent).unwrap();
1163 }
1164
1165 #[test]
1166 fn entity_id_are_consistent() {
1167 let mut world = World::new();
1168
1169 let ent1 = world.alloc();
1170 let ent2 = world.alloc();
1171 world.free(ent1);
1172 let ent3 = world.alloc();
1173
1174 assert_eq!(*world.query_one::<&Entity>(ent2).unwrap().get(), ent2);
1175 assert_eq!(*world.query_one::<&Entity>(ent3).unwrap().get(), ent3);
1176 }
1177
1178 #[test]
1179 #[should_panic]
1180 fn entity_id_cannot_be_modified() {
1181 let mut world = World::new();
1182
1183 let ent = world.alloc();
1184 let _ = world.query_one::<&mut Entity>(ent);
1185 }
1186
1187 #[test]
1188 #[should_panic]
1189 fn entity_id_cannot_be_removed() {
1190 let mut world = World::new();
1191
1192 let ent = world.alloc();
1193 let _ = world.remove::<(Entity,)>(ent);
1194 }
1195
1196 #[test]
1197 fn entity_has_niche() {
1198 assert_eq!(size_of::<Entity>(), size_of::<Option<Entity>>());
1199 }
1200
1201 #[test]
1202 fn world_can_be_cleared() {
1203 let mut world = World::new();
1204
1205 let ent1 = world.alloc();
1206 world.insert(ent1, (23,));
1207
1208 let ent2 = world.alloc();
1209 world.free(ent2);
1210
1211 assert_eq!(world.entities.len(), 2);
1212 assert_eq!(world.free_list.len(), 1);
1213
1214 assert_eq!(world.archetypes.len(), 2);
1215 assert_eq!(world.archetypes[0].len(), 0);
1216 assert_eq!(world.archetypes[1].len(), 1);
1217
1218 world.clear();
1219
1220 assert_eq!(world.entities.len(), 0);
1221 assert_eq!(world.free_list.len(), 0);
1222
1223 assert_eq!(world.archetypes.len(), 2);
1224 assert_eq!(world.archetypes[0].len(), 0);
1225 assert_eq!(world.archetypes[1].len(), 0);
1226 }
1227
1228 #[test]
1229 fn clearing_the_world_repeats_entities() {
1230 let mut world = World::new();
1231
1232 let ent = world.alloc();
1233 assert_eq!(ent.id, 0);
1234 assert_eq!(world.entities.len(), 1);
1235 assert_eq!(world.entities[0].gen.get(), 1);
1236
1237 world.clear();
1238
1239 let ent = world.alloc();
1240 assert_eq!(ent.id, 0);
1241 assert_eq!(world.entities.len(), 1);
1242 assert_eq!(world.entities[0].gen.get(), 1);
1243 }
1244
1245 #[test]
1246 fn entities_can_be_transferred_between_worlds() {
1247 let mut world1 = World::new();
1248
1249 let ent1 = world1.alloc();
1250 world1.insert(ent1, (23, true, 42.0));
1251 world1.remove::<(bool,)>(ent1);
1252
1253 let mut world2 = World::new();
1254
1255 let ent2 = world1.transfer(ent1, &mut world2);
1256
1257 assert_eq!(*world1.transfer_map.get(&(2, world2.tag)).unwrap(), 1);
1258 assert_eq!(*world2.transfer_map.get(&(1, world1.tag)).unwrap(), 2);
1259
1260 assert!(!world1.exists(ent1));
1261 assert!(world2.exists(ent2));
1262
1263 let comp = world2.query_one::<&i32>(ent2).unwrap();
1264 assert_eq!(*comp.get(), 23);
1265 }
1266
1267 #[test]
1268 fn worlds_can_be_cloned() {
1269 let mut world1 = World::new();
1270
1271 let ent = world1.alloc();
1272 world1.insert(ent, (23, true, 42.0));
1273 world1.insert(ent, ("foobar".to_owned(),));
1274
1275 let mut cloner = Cloner::new();
1276
1277 cloner.add_copyable::<i32>();
1278 cloner.add_copyable::<bool>();
1279 cloner.add_copyable::<f64>();
1280 cloner.add_cloneable::<String>();
1281
1282 let world2 = world1.clone(&cloner);
1283
1284 assert!(world1.exists(ent));
1285 assert!(world2.exists(ent));
1286
1287 let comp = world2.query_one::<&String>(ent).unwrap();
1288 assert_eq!(*comp.get(), "foobar");
1289 }
1290
1291 #[cfg(not(miri))]
1292 #[test]
1293 fn index_type_id_yields_uniformly_distributed_lower_bits() {
1294 let mut histogram = [0; 128];
1295
1296 for i in 0_u16..1024 {
1297 for t in [
1298 TypeId::of::<(i32,)>(),
1299 TypeId::of::<(bool, f32)>(),
1300 TypeId::of::<(i32, &str)>(),
1301 TypeId::of::<(bool, &str, f64)>(),
1302 ] {
1303 let mut hasher = IndexTypeIdHasher::default();
1304 (i, t).hash(&mut hasher);
1305 let hash = hasher.finish();
1306
1307 histogram[hash as usize % histogram.len()] += 1;
1308 }
1309 }
1310
1311 for count in histogram {
1312 assert_eq!(count, 1024 * 4 / histogram.len());
1313 }
1314 }
1315
1316 #[cfg(not(miri))]
1317 #[test]
1318 fn index_tag_hasher_yields_uniformly_distributed_lower_bits() {
1319 let mut histogram = [0; 128];
1320
1321 for i in 0_u16..1024 {
1322 for j in 0_u32..128 {
1323 let mut hasher = IndexTagHasher::default();
1324 (i, j).hash(&mut hasher);
1325 let hash = hasher.finish();
1326
1327 histogram[hash as usize % histogram.len()] += 1;
1328 }
1329 }
1330
1331 for count in histogram {
1332 assert_eq!(count, 1024 * 128 / histogram.len());
1333 }
1334 }
1335}