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;
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            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    /// Transfer an [Entity] and its components from this world to another.
347    ///
348    /// # Example
349    ///
350    /// ```
351    /// # use rs_ecs::*;
352    /// let mut world = World::new();
353    ///
354    /// let entity = world.alloc();
355    /// world.insert(entity, (23_i32, false, String::from("Goodbye")));
356    ///
357    /// let mut another_world = World::new();
358    /// let entity = world.transfer(entity, &mut another_world);
359    ///
360    /// let comp = another_world.query_one::<&String>(entity).unwrap();
361    /// assert_eq!(&*comp.get(), "Goodbye");
362    /// ```
363    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        // allocate entity in other
368        let new_id = other.alloc_id();
369
370        let new_meta = &mut other.entities[new_id as usize];
371
372        // free entity in self
373        meta.bump_gen();
374
375        self.free_list.push(ent.id);
376
377        // get or insert new archetype in other
378        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        // move components from old to new archetype
394        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        // fix entity component in other
406        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    /// Check if a given [Entity] exists.
444    ///
445    /// # Example
446    ///
447    /// ```
448    /// # use rs_ecs::*;
449    /// let mut world = World::new();
450    ///
451    /// let entity = world.alloc();
452    /// assert!(world.exists(entity));
453    ///
454    /// world.free(entity);
455    /// assert!(!world.exists(entity));
456    /// ```
457    pub fn exists(&self, ent: Entity) -> bool {
458        let meta = &self.entities[ent.id as usize];
459        ent.gen == meta.gen
460    }
461
462    /// Check if a certain component type is present for an [Entity].
463    ///
464    /// # Example
465    ///
466    /// ```
467    /// # use rs_ecs::*;
468    /// let mut world = World::new();
469    ///
470    /// let entity = world.alloc();
471    /// world.insert(entity, (42_u32, true));
472    ///
473    /// assert!(world.contains::<u32>(entity));
474    /// ```
475    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    /// Access the components matching given query for an [Entity].
486    ///
487    /// Note that for repeated calls, [map](crate::QueryRef::map) can be used to amortize the set-up costs.
488    ///
489    /// # Example
490    ///
491    /// ```
492    /// # use rs_ecs::*;
493    /// let mut world = World::new();
494    ///
495    /// let entity = world.alloc();
496    /// world.insert(entity, (42_u32, true));
497    ///
498    /// {
499    ///     let mut comp = world.query_one::<&mut u32>(entity).unwrap();
500    ///     *comp.get_mut() = 42;
501    /// }
502    ///
503    /// let comp = world.query_one::<&u32>(entity).unwrap();
504    /// assert_eq!(*comp.get(), 42);
505    /// ```
506    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    /// Creates a copy of the [`World`]
531    ///
532    /// This requires that all component types are available in the given [`cloner`][Cloner].
533    ///
534    /// # Example
535    ///
536    /// ```
537    /// # use rs_ecs::*;
538    /// let mut world = World::new();
539    ///
540    /// let ent = world.alloc();
541    /// world.insert(ent, (42, "foo".to_owned(),));
542    ///
543    /// let mut cloner = Cloner::new();
544    ///
545    /// cloner.add_copyable::<i32>();
546    /// cloner.add_cloneable::<String>();
547    ///
548    /// let snapshot = world.clone(&cloner);
549    ///
550    /// let mut comp = world.query_one::<&mut String>(ent).unwrap();
551    /// *comp.get_mut() = "bar".to_owned();
552    ///
553    /// let comp = snapshot.query_one::<&String>(ent).unwrap();
554    /// assert_eq!(*comp.get(), "foo");
555    /// ```
556    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/// An opaque entity identifier.
576#[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
611/// Query to access the specified components of a single entity.
612pub 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    /// Gain shared access to the specified components.
626    ///
627    /// Available only if the components do not include unique references.
628    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    /// Gain exclusive access to the specified components.
636    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}