Thanks to visit codestin.com
Credit goes to docs.rs

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