bevy_ecs/
archetype.rs

1//! Types for defining [`Archetype`]s, collections of entities that have the same set of
2//! components.
3//!
4//! An archetype uniquely describes a group of entities that share the same components:
5//! a world only has one archetype for each unique combination of components, and all
6//! entities that have those components and only those components belong to that
7//! archetype.
8//!
9//! Archetypes are not to be confused with [`Table`]s. Each archetype stores its table
10//! components in one table, and each archetype uniquely points to one table, but multiple
11//! archetypes may store their table components in the same table. These archetypes
12//! differ only by the [`SparseSet`] components.
13//!
14//! Like tables, archetypes can be created but are never cleaned up. Empty archetypes are
15//! not removed, and persist until the world is dropped.
16//!
17//! Archetypes can be fetched from [`Archetypes`], which is accessible via [`World::archetypes`].
18//!
19//! [`Table`]: crate::storage::Table
20//! [`World::archetypes`]: crate::world::World::archetypes
21
22use crate::{
23    bundle::BundleId,
24    component::{ComponentId, Components, RequiredComponentConstructor, StorageType},
25    entity::{Entity, EntityLocation},
26    observer::Observers,
27    storage::{ImmutableSparseSet, SparseArray, SparseSet, SparseSetIndex, TableId, TableRow},
28};
29use alloc::{boxed::Box, vec::Vec};
30use bevy_platform::collections::HashMap;
31use core::{
32    hash::Hash,
33    ops::{Index, IndexMut, RangeFrom},
34};
35
36/// An opaque location within a [`Archetype`].
37///
38/// This can be used in conjunction with [`ArchetypeId`] to find the exact location
39/// of an [`Entity`] within a [`World`]. An entity's archetype and index can be
40/// retrieved via [`Entities::get`].
41///
42/// [`World`]: crate::world::World
43/// [`Entities::get`]: crate::entity::Entities
44#[derive(Debug, Copy, Clone, Eq, PartialEq)]
45// SAFETY: Must be repr(transparent) due to the safety requirements on EntityLocation
46#[repr(transparent)]
47pub struct ArchetypeRow(u32);
48
49impl ArchetypeRow {
50    /// Index indicating an invalid archetype row.
51    /// This is meant to be used as a placeholder.
52    pub const INVALID: ArchetypeRow = ArchetypeRow(u32::MAX);
53
54    /// Creates a `ArchetypeRow`.
55    #[inline]
56    pub const fn new(index: usize) -> Self {
57        Self(index as u32)
58    }
59
60    /// Gets the index of the row.
61    #[inline]
62    pub const fn index(self) -> usize {
63        self.0 as usize
64    }
65}
66
67/// An opaque unique ID for a single [`Archetype`] within a [`World`].
68///
69/// Archetype IDs are only valid for a given World, and are not globally unique.
70/// Attempting to use an archetype ID on a world that it wasn't sourced from will
71/// not return the archetype with the same components. The only exception to this is
72/// [`EMPTY`] which is guaranteed to be identical for all Worlds.
73///
74/// [`World`]: crate::world::World
75/// [`EMPTY`]: ArchetypeId::EMPTY
76#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
77// SAFETY: Must be repr(transparent) due to the safety requirements on EntityLocation
78#[repr(transparent)]
79pub struct ArchetypeId(u32);
80
81impl ArchetypeId {
82    /// The ID for the [`Archetype`] without any components.
83    pub const EMPTY: ArchetypeId = ArchetypeId(0);
84    /// # Safety:
85    ///
86    /// This must always have an all-1s bit pattern to ensure soundness in fast entity id space allocation.
87    pub const INVALID: ArchetypeId = ArchetypeId(u32::MAX);
88
89    /// Create an `ArchetypeId` from a plain value.
90    ///
91    /// This is useful if you need to store the `ArchetypeId` as a plain value,
92    /// for example in a specialized data structure such as a bitset.
93    ///
94    /// While it doesn't break any safety invariants, you should ensure the
95    /// values comes from a pre-existing [`ArchetypeId::index`] in this world
96    /// to avoid panics and other unexpected behaviors.
97    #[inline]
98    pub const fn new(index: usize) -> Self {
99        ArchetypeId(index as u32)
100    }
101
102    /// The plain value of this `ArchetypeId`.
103    ///
104    /// In bevy, this is mostly used to store archetype ids in [`FixedBitSet`]s.
105    ///
106    /// [`FixedBitSet`]: fixedbitset::FixedBitSet
107    #[inline]
108    pub fn index(self) -> usize {
109        self.0 as usize
110    }
111}
112
113/// Used in [`ArchetypeAfterBundleInsert`] to track whether components in the bundle are newly
114/// added or already existed in the entity's archetype.
115#[derive(Copy, Clone, Eq, PartialEq)]
116pub(crate) enum ComponentStatus {
117    Added,
118    Existing,
119}
120
121/// Used in [`Edges`] to cache the result of inserting a bundle into the source archetype.
122pub(crate) struct ArchetypeAfterBundleInsert {
123    /// The target archetype after the bundle is inserted into the source archetype.
124    pub archetype_id: ArchetypeId,
125    /// For each component iterated in the same order as the source [`Bundle`](crate::bundle::Bundle),
126    /// indicate if the component is newly added to the target archetype or if it already existed.
127    pub bundle_status: Vec<ComponentStatus>,
128    /// The set of additional required components that must be initialized immediately when adding this Bundle.
129    ///
130    /// The initial values are determined based on the provided constructor, falling back to the `Default` trait if none is given.
131    pub required_components: Vec<RequiredComponentConstructor>,
132    /// The components added by this bundle. This includes any Required Components that are inserted when adding this bundle.
133    pub added: Vec<ComponentId>,
134    /// The components that were explicitly contributed by this bundle, but already existed in the archetype. This _does not_ include any
135    /// Required Components.
136    pub existing: Vec<ComponentId>,
137}
138
139impl ArchetypeAfterBundleInsert {
140    pub(crate) fn iter_inserted(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
141        self.added.iter().chain(self.existing.iter()).copied()
142    }
143
144    pub(crate) fn iter_added(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
145        self.added.iter().copied()
146    }
147
148    pub(crate) fn iter_existing(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
149        self.existing.iter().copied()
150    }
151}
152
153/// This trait is used to report the status of [`Bundle`](crate::bundle::Bundle) components
154/// being inserted into a given entity, relative to that entity's original archetype.
155/// See [`crate::bundle::BundleInfo::write_components`] for more info.
156pub(crate) trait BundleComponentStatus {
157    /// Returns the Bundle's component status for the given "bundle index".
158    ///
159    /// # Safety
160    /// Callers must ensure that index is always a valid bundle index for the
161    /// Bundle associated with this [`BundleComponentStatus`]
162    unsafe fn get_status(&self, index: usize) -> ComponentStatus;
163}
164
165impl BundleComponentStatus for ArchetypeAfterBundleInsert {
166    #[inline]
167    unsafe fn get_status(&self, index: usize) -> ComponentStatus {
168        // SAFETY: caller has ensured index is a valid bundle index for this bundle
169        unsafe { *self.bundle_status.get_unchecked(index) }
170    }
171}
172
173pub(crate) struct SpawnBundleStatus;
174
175impl BundleComponentStatus for SpawnBundleStatus {
176    #[inline]
177    unsafe fn get_status(&self, _index: usize) -> ComponentStatus {
178        // Components inserted during a spawn call are always treated as added.
179        ComponentStatus::Added
180    }
181}
182
183/// Archetypes and bundles form a graph. Adding or removing a bundle moves
184/// an [`Entity`] to a new [`Archetype`].
185///
186/// [`Edges`] caches the results of these moves. Each archetype caches
187/// the result of a structural alteration. This can be used to monitor the
188/// state of the archetype graph.
189///
190/// Note: This type only contains edges the [`World`] has already traversed.
191/// If any of functions return `None`, it doesn't mean there is guaranteed
192/// not to be a result of adding or removing that bundle, but rather that
193/// operation that has moved an entity along that edge has not been performed
194/// yet.
195///
196/// [`World`]: crate::world::World
197#[derive(Default)]
198pub struct Edges {
199    insert_bundle: SparseArray<BundleId, ArchetypeAfterBundleInsert>,
200    remove_bundle: SparseArray<BundleId, Option<ArchetypeId>>,
201    take_bundle: SparseArray<BundleId, Option<ArchetypeId>>,
202}
203
204impl Edges {
205    /// Checks the cache for the target archetype when inserting a bundle into the
206    /// source archetype.
207    ///
208    /// If this returns `None`, it means there has not been a transition from
209    /// the source archetype via the provided bundle.
210    #[inline]
211    pub fn get_archetype_after_bundle_insert(&self, bundle_id: BundleId) -> Option<ArchetypeId> {
212        self.get_archetype_after_bundle_insert_internal(bundle_id)
213            .map(|bundle| bundle.archetype_id)
214    }
215
216    /// Internal version of `get_archetype_after_bundle_insert` that
217    /// fetches the full `ArchetypeAfterBundleInsert`.
218    #[inline]
219    pub(crate) fn get_archetype_after_bundle_insert_internal(
220        &self,
221        bundle_id: BundleId,
222    ) -> Option<&ArchetypeAfterBundleInsert> {
223        self.insert_bundle.get(bundle_id)
224    }
225
226    /// Caches the target archetype when inserting a bundle into the source archetype.
227    #[inline]
228    pub(crate) fn cache_archetype_after_bundle_insert(
229        &mut self,
230        bundle_id: BundleId,
231        archetype_id: ArchetypeId,
232        bundle_status: Vec<ComponentStatus>,
233        required_components: Vec<RequiredComponentConstructor>,
234        added: Vec<ComponentId>,
235        existing: Vec<ComponentId>,
236    ) {
237        self.insert_bundle.insert(
238            bundle_id,
239            ArchetypeAfterBundleInsert {
240                archetype_id,
241                bundle_status,
242                required_components,
243                added,
244                existing,
245            },
246        );
247    }
248
249    /// Checks the cache for the target archetype when removing a bundle from the
250    /// source archetype.
251    ///
252    /// If this returns `None`, it means there has not been a transition from
253    /// the source archetype via the provided bundle.
254    ///
255    /// If this returns `Some(None)`, it means that the bundle cannot be removed
256    /// from the source archetype.
257    #[inline]
258    pub fn get_archetype_after_bundle_remove(
259        &self,
260        bundle_id: BundleId,
261    ) -> Option<Option<ArchetypeId>> {
262        self.remove_bundle.get(bundle_id).cloned()
263    }
264
265    /// Caches the target archetype when removing a bundle from the source archetype.
266    #[inline]
267    pub(crate) fn cache_archetype_after_bundle_remove(
268        &mut self,
269        bundle_id: BundleId,
270        archetype_id: Option<ArchetypeId>,
271    ) {
272        self.remove_bundle.insert(bundle_id, archetype_id);
273    }
274
275    /// Checks the cache for the target archetype when taking a bundle from the
276    /// source archetype.
277    ///
278    /// Unlike `remove`, `take` will only succeed if the source archetype
279    /// contains all of the components in the bundle.
280    ///
281    /// If this returns `None`, it means there has not been a transition from
282    /// the source archetype via the provided bundle.
283    ///
284    /// If this returns `Some(None)`, it means that the bundle cannot be taken
285    /// from the source archetype.
286    #[inline]
287    pub fn get_archetype_after_bundle_take(
288        &self,
289        bundle_id: BundleId,
290    ) -> Option<Option<ArchetypeId>> {
291        self.take_bundle.get(bundle_id).cloned()
292    }
293
294    /// Caches the target archetype when taking a bundle from the source archetype.
295    ///
296    /// Unlike `remove`, `take` will only succeed if the source archetype
297    /// contains all of the components in the bundle.
298    #[inline]
299    pub(crate) fn cache_archetype_after_bundle_take(
300        &mut self,
301        bundle_id: BundleId,
302        archetype_id: Option<ArchetypeId>,
303    ) {
304        self.take_bundle.insert(bundle_id, archetype_id);
305    }
306}
307
308/// Metadata about an [`Entity`] in a [`Archetype`].
309pub struct ArchetypeEntity {
310    entity: Entity,
311    table_row: TableRow,
312}
313
314impl ArchetypeEntity {
315    /// The ID of the entity.
316    #[inline]
317    pub const fn id(&self) -> Entity {
318        self.entity
319    }
320
321    /// The row in the [`Table`] where the entity's components are stored.
322    ///
323    /// [`Table`]: crate::storage::Table
324    #[inline]
325    pub const fn table_row(&self) -> TableRow {
326        self.table_row
327    }
328}
329
330/// Internal metadata for an [`Entity`] getting removed from an [`Archetype`].
331pub(crate) struct ArchetypeSwapRemoveResult {
332    /// If the [`Entity`] was not the last in the [`Archetype`], it gets removed by swapping it out
333    /// with the last entity in the archetype. In that case, this field contains the swapped entity.
334    pub(crate) swapped_entity: Option<Entity>,
335    /// The [`TableRow`] where the removed entity's components are stored.
336    pub(crate) table_row: TableRow,
337}
338
339/// Internal metadata for a [`Component`] within a given [`Archetype`].
340///
341/// [`Component`]: crate::component::Component
342struct ArchetypeComponentInfo {
343    storage_type: StorageType,
344    archetype_component_id: ArchetypeComponentId,
345}
346
347bitflags::bitflags! {
348    /// Flags used to keep track of metadata about the component in this [`Archetype`]
349    ///
350    /// Used primarily to early-out when there are no [`ComponentHook`] registered for any contained components.
351    #[derive(Clone, Copy)]
352    pub(crate) struct ArchetypeFlags: u32 {
353        const ON_ADD_HOOK    = (1 << 0);
354        const ON_INSERT_HOOK = (1 << 1);
355        const ON_REPLACE_HOOK = (1 << 2);
356        const ON_REMOVE_HOOK = (1 << 3);
357        const ON_DESPAWN_HOOK = (1 << 4);
358        const ON_ADD_OBSERVER = (1 << 5);
359        const ON_INSERT_OBSERVER = (1 << 6);
360        const ON_REPLACE_OBSERVER = (1 << 7);
361        const ON_REMOVE_OBSERVER = (1 << 8);
362        const ON_DESPAWN_OBSERVER = (1 << 9);
363    }
364}
365
366/// Metadata for a single archetype within a [`World`].
367///
368/// For more information, see the *[module level documentation]*.
369///
370/// [`World`]: crate::world::World
371/// [module level documentation]: crate::archetype
372pub struct Archetype {
373    id: ArchetypeId,
374    table_id: TableId,
375    edges: Edges,
376    entities: Vec<ArchetypeEntity>,
377    components: ImmutableSparseSet<ComponentId, ArchetypeComponentInfo>,
378    pub(crate) flags: ArchetypeFlags,
379}
380
381impl Archetype {
382    /// `table_components` and `sparse_set_components` must be sorted
383    pub(crate) fn new(
384        components: &Components,
385        component_index: &mut ComponentIndex,
386        observers: &Observers,
387        id: ArchetypeId,
388        table_id: TableId,
389        table_components: impl Iterator<Item = (ComponentId, ArchetypeComponentId)>,
390        sparse_set_components: impl Iterator<Item = (ComponentId, ArchetypeComponentId)>,
391    ) -> Self {
392        let (min_table, _) = table_components.size_hint();
393        let (min_sparse, _) = sparse_set_components.size_hint();
394        let mut flags = ArchetypeFlags::empty();
395        let mut archetype_components = SparseSet::with_capacity(min_table + min_sparse);
396        for (idx, (component_id, archetype_component_id)) in table_components.enumerate() {
397            // SAFETY: We are creating an archetype that includes this component so it must exist
398            let info = unsafe { components.get_info_unchecked(component_id) };
399            info.update_archetype_flags(&mut flags);
400            observers.update_archetype_flags(component_id, &mut flags);
401            archetype_components.insert(
402                component_id,
403                ArchetypeComponentInfo {
404                    storage_type: StorageType::Table,
405                    archetype_component_id,
406                },
407            );
408            // NOTE: the `table_components` are sorted AND they were inserted in the `Table` in the same
409            // sorted order, so the index of the `Column` in the `Table` is the same as the index of the
410            // component in the `table_components` vector
411            component_index
412                .entry(component_id)
413                .or_default()
414                .insert(id, ArchetypeRecord { column: Some(idx) });
415        }
416
417        for (component_id, archetype_component_id) in sparse_set_components {
418            // SAFETY: We are creating an archetype that includes this component so it must exist
419            let info = unsafe { components.get_info_unchecked(component_id) };
420            info.update_archetype_flags(&mut flags);
421            observers.update_archetype_flags(component_id, &mut flags);
422            archetype_components.insert(
423                component_id,
424                ArchetypeComponentInfo {
425                    storage_type: StorageType::SparseSet,
426                    archetype_component_id,
427                },
428            );
429            component_index
430                .entry(component_id)
431                .or_default()
432                .insert(id, ArchetypeRecord { column: None });
433        }
434        Self {
435            id,
436            table_id,
437            entities: Vec::new(),
438            components: archetype_components.into_immutable(),
439            edges: Default::default(),
440            flags,
441        }
442    }
443
444    /// Fetches the ID for the archetype.
445    #[inline]
446    pub fn id(&self) -> ArchetypeId {
447        self.id
448    }
449
450    /// Fetches the flags for the archetype.
451    #[inline]
452    pub(crate) fn flags(&self) -> ArchetypeFlags {
453        self.flags
454    }
455
456    /// Fetches the archetype's [`Table`] ID.
457    ///
458    /// [`Table`]: crate::storage::Table
459    #[inline]
460    pub fn table_id(&self) -> TableId {
461        self.table_id
462    }
463
464    /// Fetches the entities contained in this archetype.
465    #[inline]
466    pub fn entities(&self) -> &[ArchetypeEntity] {
467        &self.entities
468    }
469
470    /// Gets an iterator of all of the components stored in [`Table`]s.
471    ///
472    /// All of the IDs are unique.
473    ///
474    /// [`Table`]: crate::storage::Table
475    #[inline]
476    pub fn table_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
477        self.components
478            .iter()
479            .filter(|(_, component)| component.storage_type == StorageType::Table)
480            .map(|(id, _)| *id)
481    }
482
483    /// Gets an iterator of all of the components stored in [`ComponentSparseSet`]s.
484    ///
485    /// All of the IDs are unique.
486    ///
487    /// [`ComponentSparseSet`]: crate::storage::ComponentSparseSet
488    #[inline]
489    pub fn sparse_set_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
490        self.components
491            .iter()
492            .filter(|(_, component)| component.storage_type == StorageType::SparseSet)
493            .map(|(id, _)| *id)
494    }
495
496    /// Gets an iterator of all of the components in the archetype.
497    ///
498    /// All of the IDs are unique.
499    #[inline]
500    pub fn components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
501        self.components.indices()
502    }
503
504    /// Returns the total number of components in the archetype
505    #[inline]
506    pub fn component_count(&self) -> usize {
507        self.components.len()
508    }
509
510    /// Gets an iterator of all of the components in the archetype, along with
511    /// their archetype component ID.
512    pub(crate) fn components_with_archetype_component_id(
513        &self,
514    ) -> impl Iterator<Item = (ComponentId, ArchetypeComponentId)> + '_ {
515        self.components
516            .iter()
517            .map(|(component_id, info)| (*component_id, info.archetype_component_id))
518    }
519
520    /// Fetches an immutable reference to the archetype's [`Edges`], a cache of
521    /// archetypal relationships.
522    #[inline]
523    pub fn edges(&self) -> &Edges {
524        &self.edges
525    }
526
527    /// Fetches a mutable reference to the archetype's [`Edges`], a cache of
528    /// archetypal relationships.
529    #[inline]
530    pub(crate) fn edges_mut(&mut self) -> &mut Edges {
531        &mut self.edges
532    }
533
534    /// Fetches the row in the [`Table`] where the components for the entity at `index`
535    /// is stored.
536    ///
537    /// An entity's archetype row can be fetched from [`EntityLocation::archetype_row`], which
538    /// can be retrieved from [`Entities::get`].
539    ///
540    /// # Panics
541    /// This function will panic if `index >= self.len()`.
542    ///
543    /// [`Table`]: crate::storage::Table
544    /// [`EntityLocation::archetype_row`]: crate::entity::EntityLocation::archetype_row
545    /// [`Entities::get`]: crate::entity::Entities::get
546    #[inline]
547    pub fn entity_table_row(&self, row: ArchetypeRow) -> TableRow {
548        self.entities[row.index()].table_row
549    }
550
551    /// Updates if the components for the entity at `index` can be found
552    /// in the corresponding table.
553    ///
554    /// # Panics
555    /// This function will panic if `index >= self.len()`.
556    #[inline]
557    pub(crate) fn set_entity_table_row(&mut self, row: ArchetypeRow, table_row: TableRow) {
558        self.entities[row.index()].table_row = table_row;
559    }
560
561    /// Allocates an entity to the archetype.
562    ///
563    /// # Safety
564    /// valid component values must be immediately written to the relevant storages
565    /// `table_row` must be valid
566    #[inline]
567    pub(crate) unsafe fn allocate(
568        &mut self,
569        entity: Entity,
570        table_row: TableRow,
571    ) -> EntityLocation {
572        let archetype_row = ArchetypeRow::new(self.entities.len());
573        self.entities.push(ArchetypeEntity { entity, table_row });
574
575        EntityLocation {
576            archetype_id: self.id,
577            archetype_row,
578            table_id: self.table_id,
579            table_row,
580        }
581    }
582
583    #[inline]
584    pub(crate) fn reserve(&mut self, additional: usize) {
585        self.entities.reserve(additional);
586    }
587
588    /// Removes the entity at `row` by swapping it out. Returns the table row the entity is stored
589    /// in.
590    ///
591    /// # Panics
592    /// This function will panic if `row >= self.entities.len()`
593    #[inline]
594    pub(crate) fn swap_remove(&mut self, row: ArchetypeRow) -> ArchetypeSwapRemoveResult {
595        let is_last = row.index() == self.entities.len() - 1;
596        let entity = self.entities.swap_remove(row.index());
597        ArchetypeSwapRemoveResult {
598            swapped_entity: if is_last {
599                None
600            } else {
601                Some(self.entities[row.index()].entity)
602            },
603            table_row: entity.table_row,
604        }
605    }
606
607    /// Gets the total number of entities that belong to the archetype.
608    #[inline]
609    pub fn len(&self) -> usize {
610        self.entities.len()
611    }
612
613    /// Checks if the archetype has any entities.
614    #[inline]
615    pub fn is_empty(&self) -> bool {
616        self.entities.is_empty()
617    }
618
619    /// Checks if the archetype contains a specific component. This runs in `O(1)` time.
620    #[inline]
621    pub fn contains(&self, component_id: ComponentId) -> bool {
622        self.components.contains(component_id)
623    }
624
625    /// Gets the type of storage where a component in the archetype can be found.
626    /// Returns `None` if the component is not part of the archetype.
627    /// This runs in `O(1)` time.
628    #[inline]
629    pub fn get_storage_type(&self, component_id: ComponentId) -> Option<StorageType> {
630        self.components
631            .get(component_id)
632            .map(|info| info.storage_type)
633    }
634
635    /// Fetches the corresponding [`ArchetypeComponentId`] for a component in the archetype.
636    /// Returns `None` if the component is not part of the archetype.
637    /// This runs in `O(1)` time.
638    #[inline]
639    pub fn get_archetype_component_id(
640        &self,
641        component_id: ComponentId,
642    ) -> Option<ArchetypeComponentId> {
643        self.components
644            .get(component_id)
645            .map(|info| info.archetype_component_id)
646    }
647
648    /// Clears all entities from the archetype.
649    pub(crate) fn clear_entities(&mut self) {
650        self.entities.clear();
651    }
652
653    /// Returns true if any of the components in this archetype have `on_add` hooks
654    #[inline]
655    pub fn has_add_hook(&self) -> bool {
656        self.flags().contains(ArchetypeFlags::ON_ADD_HOOK)
657    }
658
659    /// Returns true if any of the components in this archetype have `on_insert` hooks
660    #[inline]
661    pub fn has_insert_hook(&self) -> bool {
662        self.flags().contains(ArchetypeFlags::ON_INSERT_HOOK)
663    }
664
665    /// Returns true if any of the components in this archetype have `on_replace` hooks
666    #[inline]
667    pub fn has_replace_hook(&self) -> bool {
668        self.flags().contains(ArchetypeFlags::ON_REPLACE_HOOK)
669    }
670
671    /// Returns true if any of the components in this archetype have `on_remove` hooks
672    #[inline]
673    pub fn has_remove_hook(&self) -> bool {
674        self.flags().contains(ArchetypeFlags::ON_REMOVE_HOOK)
675    }
676
677    /// Returns true if any of the components in this archetype have `on_despawn` hooks
678    #[inline]
679    pub fn has_despawn_hook(&self) -> bool {
680        self.flags().contains(ArchetypeFlags::ON_DESPAWN_HOOK)
681    }
682
683    /// Returns true if any of the components in this archetype have at least one [`OnAdd`] observer
684    ///
685    /// [`OnAdd`]: crate::world::OnAdd
686    #[inline]
687    pub fn has_add_observer(&self) -> bool {
688        self.flags().contains(ArchetypeFlags::ON_ADD_OBSERVER)
689    }
690
691    /// Returns true if any of the components in this archetype have at least one [`OnInsert`] observer
692    ///
693    /// [`OnInsert`]: crate::world::OnInsert
694    #[inline]
695    pub fn has_insert_observer(&self) -> bool {
696        self.flags().contains(ArchetypeFlags::ON_INSERT_OBSERVER)
697    }
698
699    /// Returns true if any of the components in this archetype have at least one [`OnReplace`] observer
700    ///
701    /// [`OnReplace`]: crate::world::OnReplace
702    #[inline]
703    pub fn has_replace_observer(&self) -> bool {
704        self.flags().contains(ArchetypeFlags::ON_REPLACE_OBSERVER)
705    }
706
707    /// Returns true if any of the components in this archetype have at least one [`OnRemove`] observer
708    ///
709    /// [`OnRemove`]: crate::world::OnRemove
710    #[inline]
711    pub fn has_remove_observer(&self) -> bool {
712        self.flags().contains(ArchetypeFlags::ON_REMOVE_OBSERVER)
713    }
714
715    /// Returns true if any of the components in this archetype have at least one [`OnDespawn`] observer
716    ///
717    /// [`OnDespawn`]: crate::world::OnDespawn
718    #[inline]
719    pub fn has_despawn_observer(&self) -> bool {
720        self.flags().contains(ArchetypeFlags::ON_DESPAWN_OBSERVER)
721    }
722}
723
724/// The next [`ArchetypeId`] in an [`Archetypes`] collection.
725///
726/// This is used in archetype update methods to limit archetype updates to the
727/// ones added since the last time the method ran.
728#[derive(Debug, Copy, Clone, PartialEq)]
729pub struct ArchetypeGeneration(pub(crate) ArchetypeId);
730
731impl ArchetypeGeneration {
732    /// The first archetype.
733    #[inline]
734    pub const fn initial() -> Self {
735        ArchetypeGeneration(ArchetypeId::EMPTY)
736    }
737}
738
739#[derive(Hash, PartialEq, Eq)]
740struct ArchetypeComponents {
741    table_components: Box<[ComponentId]>,
742    sparse_set_components: Box<[ComponentId]>,
743}
744
745/// An opaque unique joint ID for a [`Component`] in an [`Archetype`] within a [`World`].
746///
747/// A component may be present within multiple archetypes, but each component within
748/// each archetype has its own unique `ArchetypeComponentId`. This is leveraged by the system
749/// schedulers to opportunistically run multiple systems in parallel that would otherwise
750/// conflict. For example, `Query<&mut A, With<B>>` and `Query<&mut A, Without<B>>` can run in
751/// parallel as the matched `ArchetypeComponentId` sets for both queries are disjoint, even
752/// though `&mut A` on both queries point to the same [`ComponentId`].
753///
754/// In SQL terms, these IDs are composite keys on a [many-to-many relationship] between archetypes
755/// and components. Each component type will have only one [`ComponentId`], but may have many
756/// [`ArchetypeComponentId`]s, one for every archetype the component is present in. Likewise, each
757/// archetype will have only one [`ArchetypeId`] but may have many [`ArchetypeComponentId`]s, one
758/// for each component that belongs to the archetype.
759///
760/// Every [`Resource`] is also assigned one of these IDs. As resources do not belong to any
761/// particular archetype, a resource's ID uniquely identifies it.
762///
763/// These IDs are only valid within a given World, and are not globally unique.
764/// Attempting to use an ID on a world that it wasn't sourced from will
765/// not point to the same archetype nor the same component.
766///
767/// [`Component`]: crate::component::Component
768/// [`World`]: crate::world::World
769/// [`Resource`]: crate::resource::Resource
770/// [many-to-many relationship]: https://en.wikipedia.org/wiki/Many-to-many_(data_model)
771#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
772pub struct ArchetypeComponentId(usize);
773
774impl SparseSetIndex for ArchetypeComponentId {
775    #[inline]
776    fn sparse_set_index(&self) -> usize {
777        self.0
778    }
779
780    fn get_sparse_set_index(value: usize) -> Self {
781        Self(value)
782    }
783}
784
785/// Maps a [`ComponentId`] to the list of [`Archetypes`]([`Archetype`]) that contain the [`Component`](crate::component::Component),
786/// along with an [`ArchetypeRecord`] which contains some metadata about how the component is stored in the archetype.
787pub type ComponentIndex = HashMap<ComponentId, HashMap<ArchetypeId, ArchetypeRecord>>;
788
789/// The backing store of all [`Archetype`]s within a [`World`].
790///
791/// For more information, see the *[module level documentation]*.
792///
793/// [`World`]: crate::world::World
794/// [module level documentation]: crate::archetype
795pub struct Archetypes {
796    pub(crate) archetypes: Vec<Archetype>,
797    archetype_component_count: usize,
798    /// find the archetype id by the archetype's components
799    by_components: HashMap<ArchetypeComponents, ArchetypeId>,
800    /// find all the archetypes that contain a component
801    pub(crate) by_component: ComponentIndex,
802}
803
804/// Metadata about how a component is stored in an [`Archetype`].
805pub struct ArchetypeRecord {
806    /// Index of the component in the archetype's [`Table`](crate::storage::Table),
807    /// or None if the component is a sparse set component.
808    #[expect(
809        dead_code,
810        reason = "Currently unused, but planned to be used to implement a component index to improve performance of fragmenting relations."
811    )]
812    pub(crate) column: Option<usize>,
813}
814
815impl Archetypes {
816    pub(crate) fn new() -> Self {
817        let mut archetypes = Archetypes {
818            archetypes: Vec::new(),
819            by_components: Default::default(),
820            by_component: Default::default(),
821            archetype_component_count: 0,
822        };
823        // SAFETY: Empty archetype has no components
824        unsafe {
825            archetypes.get_id_or_insert(
826                &Components::default(),
827                &Observers::default(),
828                TableId::empty(),
829                Vec::new(),
830                Vec::new(),
831            );
832        }
833        archetypes
834    }
835
836    /// Returns the "generation", a handle to the current highest archetype ID.
837    ///
838    /// This can be used with the `Index` [`Archetypes`] implementation to
839    /// iterate over newly introduced [`Archetype`]s since the last time this
840    /// function was called.
841    #[inline]
842    pub fn generation(&self) -> ArchetypeGeneration {
843        let id = ArchetypeId::new(self.archetypes.len());
844        ArchetypeGeneration(id)
845    }
846
847    /// Fetches the total number of [`Archetype`]s within the world.
848    #[inline]
849    #[expect(
850        clippy::len_without_is_empty,
851        reason = "The internal vec is never empty"
852    )]
853    pub fn len(&self) -> usize {
854        self.archetypes.len()
855    }
856
857    /// Fetches an immutable reference to the archetype without any components.
858    ///
859    /// Shorthand for `archetypes.get(ArchetypeId::EMPTY).unwrap()`
860    #[inline]
861    pub fn empty(&self) -> &Archetype {
862        // SAFETY: empty archetype always exists
863        unsafe { self.archetypes.get_unchecked(ArchetypeId::EMPTY.index()) }
864    }
865
866    /// Fetches a mutable reference to the archetype without any components.
867    #[inline]
868    pub(crate) fn empty_mut(&mut self) -> &mut Archetype {
869        // SAFETY: empty archetype always exists
870        unsafe {
871            self.archetypes
872                .get_unchecked_mut(ArchetypeId::EMPTY.index())
873        }
874    }
875
876    /// Generate and store a new [`ArchetypeComponentId`].
877    ///
878    /// This simply increment the counter and return the new value.
879    ///
880    /// # Panics
881    ///
882    /// On archetype component id overflow.
883    pub(crate) fn new_archetype_component_id(&mut self) -> ArchetypeComponentId {
884        let id = ArchetypeComponentId(self.archetype_component_count);
885        self.archetype_component_count = self
886            .archetype_component_count
887            .checked_add(1)
888            .expect("archetype_component_count overflow");
889        id
890    }
891
892    /// Fetches an immutable reference to an [`Archetype`] using its
893    /// ID. Returns `None` if no corresponding archetype exists.
894    #[inline]
895    pub fn get(&self, id: ArchetypeId) -> Option<&Archetype> {
896        self.archetypes.get(id.index())
897    }
898
899    /// # Panics
900    ///
901    /// Panics if `a` and `b` are equal.
902    #[inline]
903    pub(crate) fn get_2_mut(
904        &mut self,
905        a: ArchetypeId,
906        b: ArchetypeId,
907    ) -> (&mut Archetype, &mut Archetype) {
908        if a.index() > b.index() {
909            let (b_slice, a_slice) = self.archetypes.split_at_mut(a.index());
910            (&mut a_slice[0], &mut b_slice[b.index()])
911        } else {
912            let (a_slice, b_slice) = self.archetypes.split_at_mut(b.index());
913            (&mut a_slice[a.index()], &mut b_slice[0])
914        }
915    }
916
917    /// Returns a read-only iterator over all archetypes.
918    #[inline]
919    pub fn iter(&self) -> impl Iterator<Item = &Archetype> {
920        self.archetypes.iter()
921    }
922
923    /// Gets the archetype id matching the given inputs or inserts a new one if it doesn't exist.
924    /// `table_components` and `sparse_set_components` must be sorted
925    ///
926    /// # Safety
927    /// [`TableId`] must exist in tables
928    /// `table_components` and `sparse_set_components` must exist in `components`
929    pub(crate) unsafe fn get_id_or_insert(
930        &mut self,
931        components: &Components,
932        observers: &Observers,
933        table_id: TableId,
934        table_components: Vec<ComponentId>,
935        sparse_set_components: Vec<ComponentId>,
936    ) -> ArchetypeId {
937        let archetype_identity = ArchetypeComponents {
938            sparse_set_components: sparse_set_components.into_boxed_slice(),
939            table_components: table_components.into_boxed_slice(),
940        };
941
942        let archetypes = &mut self.archetypes;
943        let archetype_component_count = &mut self.archetype_component_count;
944        let component_index = &mut self.by_component;
945        *self
946            .by_components
947            .entry(archetype_identity)
948            .or_insert_with_key(move |identity| {
949                let ArchetypeComponents {
950                    table_components,
951                    sparse_set_components,
952                } = identity;
953                let id = ArchetypeId::new(archetypes.len());
954                let table_start = *archetype_component_count;
955                *archetype_component_count += table_components.len();
956                let table_archetype_components =
957                    (table_start..*archetype_component_count).map(ArchetypeComponentId);
958                let sparse_start = *archetype_component_count;
959                *archetype_component_count += sparse_set_components.len();
960                let sparse_set_archetype_components =
961                    (sparse_start..*archetype_component_count).map(ArchetypeComponentId);
962                archetypes.push(Archetype::new(
963                    components,
964                    component_index,
965                    observers,
966                    id,
967                    table_id,
968                    table_components
969                        .iter()
970                        .copied()
971                        .zip(table_archetype_components),
972                    sparse_set_components
973                        .iter()
974                        .copied()
975                        .zip(sparse_set_archetype_components),
976                ));
977                id
978            })
979    }
980
981    /// Returns the number of components that are stored in archetypes.
982    /// Note that if some component `T` is stored in more than one archetype, it will be counted once for each archetype it's present in.
983    #[inline]
984    pub fn archetype_components_len(&self) -> usize {
985        self.archetype_component_count
986    }
987
988    /// Clears all entities from all archetypes.
989    pub(crate) fn clear_entities(&mut self) {
990        for archetype in &mut self.archetypes {
991            archetype.clear_entities();
992        }
993    }
994
995    /// Get the component index
996    pub(crate) fn component_index(&self) -> &ComponentIndex {
997        &self.by_component
998    }
999
1000    pub(crate) fn update_flags(
1001        &mut self,
1002        component_id: ComponentId,
1003        flags: ArchetypeFlags,
1004        set: bool,
1005    ) {
1006        if let Some(archetypes) = self.by_component.get(&component_id) {
1007            for archetype_id in archetypes.keys() {
1008                // SAFETY: the component index only contains valid archetype ids
1009                self.archetypes
1010                    .get_mut(archetype_id.index())
1011                    .unwrap()
1012                    .flags
1013                    .set(flags, set);
1014            }
1015        }
1016    }
1017}
1018
1019impl Index<RangeFrom<ArchetypeGeneration>> for Archetypes {
1020    type Output = [Archetype];
1021
1022    #[inline]
1023    fn index(&self, index: RangeFrom<ArchetypeGeneration>) -> &Self::Output {
1024        &self.archetypes[index.start.0.index()..]
1025    }
1026}
1027impl Index<ArchetypeId> for Archetypes {
1028    type Output = Archetype;
1029
1030    #[inline]
1031    fn index(&self, index: ArchetypeId) -> &Self::Output {
1032        &self.archetypes[index.index()]
1033    }
1034}
1035
1036impl IndexMut<ArchetypeId> for Archetypes {
1037    #[inline]
1038    fn index_mut(&mut self, index: ArchetypeId) -> &mut Self::Output {
1039        &mut self.archetypes[index.index()]
1040    }
1041}