Skip to main content

rs_ecs/
world.rs

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
16/// The world storing entities and their components.
17pub 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    /// Create an empty world.
29    fn default() -> Self {
30        Self::new()
31    }
32}
33
34impl World {
35    /// Create an empty world.
36    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    /// Create an [Entity] without any components.
69    /// To add components, see [Self::insert()].
70    ///
71    /// # Example
72    ///
73    /// ```
74    /// # use rs_ecs::*;
75    /// let mut world = World::new();
76    ///
77    /// let entity = world.alloc();
78    /// world.insert(entity, (42_u32, true));
79    /// ```
80    #[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    /// Remove an [Entity] and all its components from the world.
110    /// To remove components, see [Self::remove()].
111    ///
112    /// # Example
113    ///
114    /// ```
115    /// # use rs_ecs::*;
116    /// let mut world = World::new();
117    ///
118    /// let entity = world.alloc();
119    /// world.insert(entity, (42_u32, true));
120    ///
121    /// world.free(entity);
122    /// ```
123    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    /// Remove all entites and their components from the world.
153    ///
154    /// Note that this will re-use the memory allocations but it will drop the meta-data
155    /// which implies that previously used [`Entity`] values will be repeated.
156    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    /// Insert components for a given [Entity].
173    ///
174    /// If a component is already present for the entity, its value will be overwritten.
175    ///
176    /// # Example
177    ///
178    /// ```
179    /// # use rs_ecs::*;
180    /// let mut world = World::new();
181    ///
182    /// let entity = world.alloc();
183    /// world.insert(entity, (42_u32, true));
184    /// world.insert(entity, (String::from("Hello"),));
185    /// ```
186    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    /// Remove components for a given [Entity].
194    ///
195    /// # Example
196    ///
197    /// ```
198    /// # use rs_ecs::*;
199    /// let mut world = World::new();
200    ///
201    /// let entity = world.alloc();
202    /// world.insert(entity, (42_u32, true, String::from("Hello")));
203    ///
204    /// world.remove::<(u32, bool)>(entity).unwrap();
205    /// world.remove::<(String,)>(entity).unwrap();
206    /// ```
207    pub fn remove<B>(&mut self, ent: Entity) -> Option<B>
208    where
209        B: Bundle,
210    {
211        self.exchange::<B, ()>(ent, ())
212    }
213
214    /// Exchange components for a given [Entity]
215    ///
216    /// # Example
217    ///
218    /// ```
219    /// # use rs_ecs::*;
220    /// let mut world = World::new();
221    ///
222    /// let entity = world.alloc();
223    /// world.insert(entity, (42_u32, true));
224    /// assert!(world.contains::<u32>(entity));
225    /// assert!(world.contains::<bool>(entity));
226    /// assert!(!world.contains::<String>(entity));
227    ///
228    /// world.exchange::<(u32, bool), _>(entity, (String::from("Hello"),)).unwrap();
229    /// assert!(!world.contains::<u32>(entity));
230    /// assert!(!world.contains::<bool>(entity));
231    /// assert!(world.contains::<String>(entity));
232    /// ```
233    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    /// Transfer an [Entity] and its components from this world to another.
379    ///
380    /// # Example
381    ///
382    /// ```
383    /// # use rs_ecs::*;
384    /// let mut world = World::new();
385    ///
386    /// let entity = world.alloc();
387    /// world.insert(entity, (23_i32, false, String::from("Goodbye")));
388    ///
389    /// let mut another_world = World::new();
390    /// let entity = world.transfer(entity, &mut another_world);
391    ///
392    /// let comp = another_world.query_one::<&String>(entity).unwrap();
393    /// assert_eq!(&*comp.get(), "Goodbye");
394    /// ```
395    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        // allocate entity in other
400        let new_id = other.alloc_id();
401
402        let new_meta = &mut other.entities[new_id as usize];
403
404        // free entity in self
405        meta.bump_gen();
406
407        self.free_list.push(ent.id);
408
409        // get or insert new archetype in other
410        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        // move components from old to new archetype
426        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        // fix entity component in other
438        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    /// Check if a given [Entity] exists.
476    ///
477    /// # Example
478    ///
479    /// ```
480    /// # use rs_ecs::*;
481    /// let mut world = World::new();
482    ///
483    /// let entity = world.alloc();
484    /// assert!(world.exists(entity));
485    ///
486    /// world.free(entity);
487    /// assert!(!world.exists(entity));
488    /// ```
489    pub fn exists(&self, ent: Entity) -> bool {
490        let meta = &self.entities[ent.id as usize];
491        ent.gen == meta.gen
492    }
493
494    /// Check if a certain component type is present for an [Entity].
495    ///
496    /// # Example
497    ///
498    /// ```
499    /// # use rs_ecs::*;
500    /// let mut world = World::new();
501    ///
502    /// let entity = world.alloc();
503    /// world.insert(entity, (42_u32, true));
504    ///
505    /// assert!(world.contains::<u32>(entity));
506    /// ```
507    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    /// Access the components matching given query for an [Entity].
518    ///
519    /// Note that for repeated calls, [map](crate::QueryRef::map) can be used to amortize the set-up costs.
520    ///
521    /// # Example
522    ///
523    /// ```
524    /// # use rs_ecs::*;
525    /// let mut world = World::new();
526    ///
527    /// let entity = world.alloc();
528    /// world.insert(entity, (42_u32, true));
529    ///
530    /// {
531    ///     let mut comp = world.query_one::<&mut u32>(entity).unwrap();
532    ///     *comp.get_mut() = 42;
533    /// }
534    ///
535    /// let comp = world.query_one::<&u32>(entity).unwrap();
536    /// assert_eq!(*comp.get(), 42);
537    /// ```
538    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    /// Creates a copy of the [`World`]
563    ///
564    /// This requires that all component types are available in the given [`cloner`][Cloner].
565    ///
566    /// # Example
567    ///
568    /// ```
569    /// # use rs_ecs::*;
570    /// let mut world = World::new();
571    ///
572    /// let ent = world.alloc();
573    /// world.insert(ent, (42, "foo".to_owned(),));
574    ///
575    /// let mut cloner = Cloner::new();
576    ///
577    /// cloner.add_copyable::<i32>();
578    /// cloner.add_cloneable::<String>();
579    ///
580    /// let snapshot = world.clone(&cloner);
581    ///
582    /// let mut comp = world.query_one::<&mut String>(ent).unwrap();
583    /// *comp.get_mut() = "bar".to_owned();
584    ///
585    /// let comp = snapshot.query_one::<&String>(ent).unwrap();
586    /// assert_eq!(*comp.get(), "foo");
587    /// ```
588    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/// An opaque entity identifier.
608#[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
643/// Query to access the specified components of a single entity.
644pub 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    /// Gain shared access to the specified components.
658    ///
659    /// Available only if the components do not include unique references.
660    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    /// Gain exclusive access to the specified components.
668    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}