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