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