bevy_ecs/entity/
mod.rs

1//! Entity handling types.
2//!
3//! An **entity** exclusively owns zero or more [component] instances, all of different types, and can dynamically acquire or lose them over its lifetime.
4//!
5//! **empty entity**: Entity with zero components.
6//! **pending entity**: Entity reserved, but not flushed yet (see [`Entities::flush`] docs for reference).
7//! **reserved entity**: same as **pending entity**.
8//! **invalid entity**: **pending entity** flushed with invalid (see [`Entities::flush_as_invalid`] docs for reference).
9//!
10//! See [`Entity`] to learn more.
11//!
12//! [component]: crate::component::Component
13//!
14//! # Usage
15//!
16//! Operations involving entities and their components are performed either from a system by submitting commands,
17//! or from the outside (or from an exclusive system) by directly using [`World`] methods:
18//!
19//! |Operation|Command|Method|
20//! |:---:|:---:|:---:|
21//! |Spawn an entity with components|[`Commands::spawn`]|[`World::spawn`]|
22//! |Spawn an entity without components|[`Commands::spawn_empty`]|[`World::spawn_empty`]|
23//! |Despawn an entity|[`EntityCommands::despawn`]|[`World::despawn`]|
24//! |Insert a component, bundle, or tuple of components and bundles to an entity|[`EntityCommands::insert`]|[`EntityWorldMut::insert`]|
25//! |Remove a component, bundle, or tuple of components and bundles from an entity|[`EntityCommands::remove`]|[`EntityWorldMut::remove`]|
26//!
27//! [`World`]: crate::world::World
28//! [`Commands::spawn`]: crate::system::Commands::spawn
29//! [`Commands::spawn_empty`]: crate::system::Commands::spawn_empty
30//! [`EntityCommands::despawn`]: crate::system::EntityCommands::despawn
31//! [`EntityCommands::insert`]: crate::system::EntityCommands::insert
32//! [`EntityCommands::remove`]: crate::system::EntityCommands::remove
33//! [`World::spawn`]: crate::world::World::spawn
34//! [`World::spawn_empty`]: crate::world::World::spawn_empty
35//! [`World::despawn`]: crate::world::World::despawn
36//! [`EntityWorldMut::insert`]: crate::world::EntityWorldMut::insert
37//! [`EntityWorldMut::remove`]: crate::world::EntityWorldMut::remove
38mod map_entities;
39mod visit_entities;
40#[cfg(feature = "bevy_reflect")]
41use bevy_reflect::Reflect;
42#[cfg(all(feature = "bevy_reflect", feature = "serialize"))]
43use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
44pub use map_entities::*;
45pub use visit_entities::*;
46
47mod hash;
48pub use hash::*;
49
50use bevy_utils::tracing::warn;
51
52use crate::{
53    archetype::{ArchetypeId, ArchetypeRow},
54    identifier::{
55        error::IdentifierError,
56        kinds::IdKind,
57        masks::{IdentifierMask, HIGH_MASK},
58        Identifier,
59    },
60    storage::{SparseSetIndex, TableId, TableRow},
61};
62use core::{fmt, hash::Hash, mem, num::NonZero, sync::atomic::Ordering};
63#[cfg(feature = "serialize")]
64use serde::{Deserialize, Serialize};
65
66#[cfg(target_has_atomic = "64")]
67use core::sync::atomic::AtomicI64 as AtomicIdCursor;
68#[cfg(target_has_atomic = "64")]
69type IdCursor = i64;
70
71/// Most modern platforms support 64-bit atomics, but some less-common platforms
72/// do not. This fallback allows compilation using a 32-bit cursor instead, with
73/// the caveat that some conversions may fail (and panic) at runtime.
74#[cfg(not(target_has_atomic = "64"))]
75use core::sync::atomic::AtomicIsize as AtomicIdCursor;
76#[cfg(not(target_has_atomic = "64"))]
77type IdCursor = isize;
78
79/// Lightweight identifier of an [entity](crate::entity).
80///
81/// The identifier is implemented using a [generational index]: a combination of an index and a generation.
82/// This allows fast insertion after data removal in an array while minimizing loss of spatial locality.
83///
84/// These identifiers are only valid on the [`World`] it's sourced from. Attempting to use an `Entity` to
85/// fetch entity components or metadata from a different world will either fail or return unexpected results.
86///
87/// [generational index]: https://lucassardois.medium.com/generational-indices-guide-8e3c5f7fd594
88///
89/// # Stability warning
90/// For all intents and purposes, `Entity` should be treated as an opaque identifier. The internal bit
91/// representation is liable to change from release to release as are the behaviors or performance
92/// characteristics of any of its trait implementations (i.e. `Ord`, `Hash`, etc.). This means that changes in
93/// `Entity`'s representation, though made readable through various functions on the type, are not considered
94/// breaking changes under [SemVer].
95///
96/// In particular, directly serializing with `Serialize` and `Deserialize` make zero guarantee of long
97/// term wire format compatibility. Changes in behavior will cause serialized `Entity` values persisted
98/// to long term storage (i.e. disk, databases, etc.) will fail to deserialize upon being updated.
99///
100/// # Usage
101///
102/// This data type is returned by iterating a `Query` that has `Entity` as part of its query fetch type parameter ([learn more]).
103/// It can also be obtained by calling [`EntityCommands::id`] or [`EntityWorldMut::id`].
104///
105/// ```
106/// # use bevy_ecs::prelude::*;
107/// # #[derive(Component)]
108/// # struct SomeComponent;
109/// fn setup(mut commands: Commands) {
110///     // Calling `spawn` returns `EntityCommands`.
111///     let entity = commands.spawn(SomeComponent).id();
112/// }
113///
114/// fn exclusive_system(world: &mut World) {
115///     // Calling `spawn` returns `EntityWorldMut`.
116///     let entity = world.spawn(SomeComponent).id();
117/// }
118/// #
119/// # bevy_ecs::system::assert_is_system(setup);
120/// # bevy_ecs::system::assert_is_system(exclusive_system);
121/// ```
122///
123/// It can be used to refer to a specific entity to apply [`EntityCommands`], or to call [`Query::get`] (or similar methods) to access its components.
124///
125/// ```
126/// # use bevy_ecs::prelude::*;
127/// #
128/// # #[derive(Component)]
129/// # struct Expired;
130/// #
131/// fn dispose_expired_food(mut commands: Commands, query: Query<Entity, With<Expired>>) {
132///     for food_entity in &query {
133///         commands.entity(food_entity).despawn();
134///     }
135/// }
136/// #
137/// # bevy_ecs::system::assert_is_system(dispose_expired_food);
138/// ```
139///
140/// [learn more]: crate::system::Query#entity-id-access
141/// [`EntityCommands::id`]: crate::system::EntityCommands::id
142/// [`EntityWorldMut::id`]: crate::world::EntityWorldMut::id
143/// [`EntityCommands`]: crate::system::EntityCommands
144/// [`Query::get`]: crate::system::Query::get
145/// [`World`]: crate::world::World
146/// [SemVer]: https://semver.org/
147#[derive(Clone, Copy)]
148#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
149#[cfg_attr(feature = "bevy_reflect", reflect(opaque))]
150#[cfg_attr(feature = "bevy_reflect", reflect(Hash, PartialEq, Debug))]
151#[cfg_attr(
152    all(feature = "bevy_reflect", feature = "serialize"),
153    reflect(Serialize, Deserialize)
154)]
155// Alignment repr necessary to allow LLVM to better output
156// optimized codegen for `to_bits`, `PartialEq` and `Ord`.
157#[repr(C, align(8))]
158pub struct Entity {
159    // Do not reorder the fields here. The ordering is explicitly used by repr(C)
160    // to make this struct equivalent to a u64.
161    #[cfg(target_endian = "little")]
162    index: u32,
163    generation: NonZero<u32>,
164    #[cfg(target_endian = "big")]
165    index: u32,
166}
167
168// By not short-circuiting in comparisons, we get better codegen.
169// See <https://github.com/rust-lang/rust/issues/117800>
170impl PartialEq for Entity {
171    #[inline]
172    fn eq(&self, other: &Entity) -> bool {
173        // By using `to_bits`, the codegen can be optimized out even
174        // further potentially. Relies on the correct alignment/field
175        // order of `Entity`.
176        self.to_bits() == other.to_bits()
177    }
178}
179
180impl Eq for Entity {}
181
182// The derive macro codegen output is not optimal and can't be optimized as well
183// by the compiler. This impl resolves the issue of non-optimal codegen by relying
184// on comparing against the bit representation of `Entity` instead of comparing
185// the fields. The result is then LLVM is able to optimize the codegen for Entity
186// far beyond what the derive macro can.
187// See <https://github.com/rust-lang/rust/issues/106107>
188impl PartialOrd for Entity {
189    #[inline]
190    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
191        // Make use of our `Ord` impl to ensure optimal codegen output
192        Some(self.cmp(other))
193    }
194}
195
196// The derive macro codegen output is not optimal and can't be optimized as well
197// by the compiler. This impl resolves the issue of non-optimal codegen by relying
198// on comparing against the bit representation of `Entity` instead of comparing
199// the fields. The result is then LLVM is able to optimize the codegen for Entity
200// far beyond what the derive macro can.
201// See <https://github.com/rust-lang/rust/issues/106107>
202impl Ord for Entity {
203    #[inline]
204    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
205        // This will result in better codegen for ordering comparisons, plus
206        // avoids pitfalls with regards to macro codegen relying on property
207        // position when we want to compare against the bit representation.
208        self.to_bits().cmp(&other.to_bits())
209    }
210}
211
212impl Hash for Entity {
213    #[inline]
214    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
215        self.to_bits().hash(state);
216    }
217}
218
219pub(crate) enum AllocAtWithoutReplacement {
220    Exists(EntityLocation),
221    DidNotExist,
222    ExistsWithWrongGeneration,
223}
224
225impl Entity {
226    /// Construct an [`Entity`] from a raw `index` value and a non-zero `generation` value.
227    /// Ensure that the generation value is never greater than `0x7FFF_FFFF`.
228    #[inline(always)]
229    pub(crate) const fn from_raw_and_generation(index: u32, generation: NonZero<u32>) -> Entity {
230        debug_assert!(generation.get() <= HIGH_MASK);
231
232        Self { index, generation }
233    }
234
235    /// An entity ID with a placeholder value. This may or may not correspond to an actual entity,
236    /// and should be overwritten by a new value before being used.
237    ///
238    /// ## Examples
239    ///
240    /// Initializing a collection (e.g. `array` or `Vec`) with a known size:
241    ///
242    /// ```no_run
243    /// # use bevy_ecs::prelude::*;
244    /// // Create a new array of size 10 filled with invalid entity ids.
245    /// let mut entities: [Entity; 10] = [Entity::PLACEHOLDER; 10];
246    ///
247    /// // ... replace the entities with valid ones.
248    /// ```
249    ///
250    /// Deriving [`Reflect`] for a component that has an `Entity` field:
251    ///
252    /// ```no_run
253    /// # use bevy_ecs::{prelude::*, component::*};
254    /// # use bevy_reflect::Reflect;
255    /// #[derive(Reflect, Component)]
256    /// #[reflect(Component)]
257    /// pub struct MyStruct {
258    ///     pub entity: Entity,
259    /// }
260    ///
261    /// impl FromWorld for MyStruct {
262    ///     fn from_world(_world: &mut World) -> Self {
263    ///         Self {
264    ///             entity: Entity::PLACEHOLDER,
265    ///         }
266    ///     }
267    /// }
268    /// ```
269    pub const PLACEHOLDER: Self = Self::from_raw(u32::MAX);
270
271    /// Creates a new entity ID with the specified `index` and a generation of 1.
272    ///
273    /// # Note
274    ///
275    /// Spawning a specific `entity` value is __rarely the right choice__. Most apps should favor
276    /// [`Commands::spawn`](crate::system::Commands::spawn). This method should generally
277    /// only be used for sharing entities across apps, and only when they have a scheme
278    /// worked out to share an index space (which doesn't happen by default).
279    ///
280    /// In general, one should not try to synchronize the ECS by attempting to ensure that
281    /// `Entity` lines up between instances, but instead insert a secondary identifier as
282    /// a component.
283    #[inline(always)]
284    pub const fn from_raw(index: u32) -> Entity {
285        Self::from_raw_and_generation(index, NonZero::<u32>::MIN)
286    }
287
288    /// Convert to a form convenient for passing outside of rust.
289    ///
290    /// Only useful for identifying entities within the same instance of an application. Do not use
291    /// for serialization between runs.
292    ///
293    /// No particular structure is guaranteed for the returned bits.
294    #[inline(always)]
295    pub const fn to_bits(self) -> u64 {
296        IdentifierMask::pack_into_u64(self.index, self.generation.get())
297    }
298
299    /// Reconstruct an `Entity` previously destructured with [`Entity::to_bits`].
300    ///
301    /// Only useful when applied to results from `to_bits` in the same instance of an application.
302    ///
303    /// # Panics
304    ///
305    /// This method will likely panic if given `u64` values that did not come from [`Entity::to_bits`].
306    #[inline]
307    pub const fn from_bits(bits: u64) -> Self {
308        // Construct an Identifier initially to extract the kind from.
309        let id = Self::try_from_bits(bits);
310
311        match id {
312            Ok(entity) => entity,
313            Err(_) => panic!("Attempted to initialize invalid bits as an entity"),
314        }
315    }
316
317    /// Reconstruct an `Entity` previously destructured with [`Entity::to_bits`].
318    ///
319    /// Only useful when applied to results from `to_bits` in the same instance of an application.
320    ///
321    /// This method is the fallible counterpart to [`Entity::from_bits`].
322    #[inline(always)]
323    pub const fn try_from_bits(bits: u64) -> Result<Self, IdentifierError> {
324        if let Ok(id) = Identifier::try_from_bits(bits) {
325            let kind = id.kind() as u8;
326
327            if kind == (IdKind::Entity as u8) {
328                return Ok(Self {
329                    index: id.low(),
330                    generation: id.high(),
331                });
332            }
333        }
334
335        Err(IdentifierError::InvalidEntityId(bits))
336    }
337
338    /// Return a transiently unique identifier.
339    ///
340    /// No two simultaneously-live entities share the same index, but dead entities' indices may collide
341    /// with both live and dead entities. Useful for compactly representing entities within a
342    /// specific snapshot of the world, such as when serializing.
343    #[inline]
344    pub const fn index(self) -> u32 {
345        self.index
346    }
347
348    /// Returns the generation of this Entity's index. The generation is incremented each time an
349    /// entity with a given index is despawned. This serves as a "count" of the number of times a
350    /// given index has been reused (index, generation) pairs uniquely identify a given Entity.
351    #[inline]
352    pub const fn generation(self) -> u32 {
353        // Mask so not to expose any flags
354        IdentifierMask::extract_value_from_high(self.generation.get())
355    }
356}
357
358impl TryFrom<Identifier> for Entity {
359    type Error = IdentifierError;
360
361    #[inline]
362    fn try_from(value: Identifier) -> Result<Self, Self::Error> {
363        Self::try_from_bits(value.to_bits())
364    }
365}
366
367impl From<Entity> for Identifier {
368    #[inline]
369    fn from(value: Entity) -> Self {
370        Identifier::from_bits(value.to_bits())
371    }
372}
373
374#[cfg(feature = "serialize")]
375impl Serialize for Entity {
376    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
377    where
378        S: serde::Serializer,
379    {
380        serializer.serialize_u64(self.to_bits())
381    }
382}
383
384#[cfg(feature = "serialize")]
385impl<'de> Deserialize<'de> for Entity {
386    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387    where
388        D: serde::Deserializer<'de>,
389    {
390        use serde::de::Error;
391        let id: u64 = Deserialize::deserialize(deserializer)?;
392        Entity::try_from_bits(id).map_err(D::Error::custom)
393    }
394}
395
396/// Outputs the full entity identifier, including the index, generation, and the raw bits.
397///
398/// This takes the format: `{index}v{generation}#{bits}`.
399///
400/// For [`Entity::PLACEHOLDER`], this outputs `PLACEHOLDER`.
401///
402/// # Usage
403///
404/// Prefer to use this format for debugging and logging purposes. Because the output contains
405/// the raw bits, it is easy to check it against serialized scene data.
406///
407/// Example serialized scene data:
408/// ```text
409/// (
410///   ...
411///   entities: {
412///     4294967297: (  <--- Raw Bits
413///       components: {
414///         ...
415///       ),
416///   ...
417/// )
418/// ```
419impl fmt::Debug for Entity {
420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421        if self == &Self::PLACEHOLDER {
422            write!(f, "PLACEHOLDER")
423        } else {
424            write!(
425                f,
426                "{}v{}#{}",
427                self.index(),
428                self.generation(),
429                self.to_bits()
430            )
431        }
432    }
433}
434
435/// Outputs the short entity identifier, including the index and generation.
436///
437/// This takes the format: `{index}v{generation}`.
438///
439/// For [`Entity::PLACEHOLDER`], this outputs `PLACEHOLDER`.
440impl fmt::Display for Entity {
441    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
442        if self == &Self::PLACEHOLDER {
443            write!(f, "PLACEHOLDER")
444        } else {
445            write!(f, "{}v{}", self.index(), self.generation())
446        }
447    }
448}
449
450impl SparseSetIndex for Entity {
451    #[inline]
452    fn sparse_set_index(&self) -> usize {
453        self.index() as usize
454    }
455
456    #[inline]
457    fn get_sparse_set_index(value: usize) -> Self {
458        Entity::from_raw(value as u32)
459    }
460}
461
462/// An [`Iterator`] returning a sequence of [`Entity`] values from
463pub struct ReserveEntitiesIterator<'a> {
464    // Metas, so we can recover the current generation for anything in the freelist.
465    meta: &'a [EntityMeta],
466
467    // Reserved indices formerly in the freelist to hand out.
468    freelist_indices: core::slice::Iter<'a, u32>,
469
470    // New Entity indices to hand out, outside the range of meta.len().
471    new_indices: core::ops::Range<u32>,
472}
473
474impl<'a> Iterator for ReserveEntitiesIterator<'a> {
475    type Item = Entity;
476
477    fn next(&mut self) -> Option<Self::Item> {
478        self.freelist_indices
479            .next()
480            .map(|&index| {
481                Entity::from_raw_and_generation(index, self.meta[index as usize].generation)
482            })
483            .or_else(|| self.new_indices.next().map(Entity::from_raw))
484    }
485
486    fn size_hint(&self) -> (usize, Option<usize>) {
487        let len = self.freelist_indices.len() + self.new_indices.len();
488        (len, Some(len))
489    }
490}
491
492impl<'a> ExactSizeIterator for ReserveEntitiesIterator<'a> {}
493impl<'a> core::iter::FusedIterator for ReserveEntitiesIterator<'a> {}
494
495/// A [`World`]'s internal metadata store on all of its entities.
496///
497/// Contains metadata on:
498///  - The generation of every entity.
499///  - The alive/dead status of a particular entity. (i.e. "has entity 3 been despawned?")
500///  - The location of the entity's components in memory (via [`EntityLocation`])
501///
502/// [`World`]: crate::world::World
503#[derive(Debug)]
504pub struct Entities {
505    meta: Vec<EntityMeta>,
506
507    /// The `pending` and `free_cursor` fields describe three sets of Entity IDs
508    /// that have been freed or are in the process of being allocated:
509    ///
510    /// - The `freelist` IDs, previously freed by `free()`. These IDs are available to any of
511    ///   [`alloc`], [`reserve_entity`] or [`reserve_entities`]. Allocation will always prefer
512    ///   these over brand new IDs.
513    ///
514    /// - The `reserved` list of IDs that were once in the freelist, but got reserved by
515    ///   [`reserve_entities`] or [`reserve_entity`]. They are now waiting for [`flush`] to make them
516    ///   fully allocated.
517    ///
518    /// - The count of new IDs that do not yet exist in `self.meta`, but which we have handed out
519    ///   and reserved. [`flush`] will allocate room for them in `self.meta`.
520    ///
521    /// The contents of `pending` look like this:
522    ///
523    /// ```txt
524    /// ----------------------------
525    /// |  freelist  |  reserved   |
526    /// ----------------------------
527    ///              ^             ^
528    ///          free_cursor   pending.len()
529    /// ```
530    ///
531    /// As IDs are allocated, `free_cursor` is atomically decremented, moving
532    /// items from the freelist into the reserved list by sliding over the boundary.
533    ///
534    /// Once the freelist runs out, `free_cursor` starts going negative.
535    /// The more negative it is, the more IDs have been reserved starting exactly at
536    /// the end of `meta.len()`.
537    ///
538    /// This formulation allows us to reserve any number of IDs first from the freelist
539    /// and then from the new IDs, using only a single atomic subtract.
540    ///
541    /// Once [`flush`] is done, `free_cursor` will equal `pending.len()`.
542    ///
543    /// [`alloc`]: Entities::alloc
544    /// [`reserve_entity`]: Entities::reserve_entity
545    /// [`reserve_entities`]: Entities::reserve_entities
546    /// [`flush`]: Entities::flush
547    pending: Vec<u32>,
548    free_cursor: AtomicIdCursor,
549    /// Stores the number of free entities for [`len`](Entities::len)
550    len: u32,
551}
552
553impl Entities {
554    pub(crate) const fn new() -> Self {
555        Entities {
556            meta: Vec::new(),
557            pending: Vec::new(),
558            free_cursor: AtomicIdCursor::new(0),
559            len: 0,
560        }
561    }
562
563    /// Reserve entity IDs concurrently.
564    ///
565    /// Storage for entity generation and location is lazily allocated by calling [`flush`](Entities::flush).
566    #[allow(clippy::unnecessary_fallible_conversions)] // Because `IdCursor::try_from` may fail on 32-bit platforms.
567    pub fn reserve_entities(&self, count: u32) -> ReserveEntitiesIterator {
568        // Use one atomic subtract to grab a range of new IDs. The range might be
569        // entirely nonnegative, meaning all IDs come from the freelist, or entirely
570        // negative, meaning they are all new IDs to allocate, or a mix of both.
571        let range_end = self.free_cursor.fetch_sub(
572            IdCursor::try_from(count)
573                .expect("64-bit atomic operations are not supported on this platform."),
574            Ordering::Relaxed,
575        );
576        let range_start = range_end
577            - IdCursor::try_from(count)
578                .expect("64-bit atomic operations are not supported on this platform.");
579
580        let freelist_range = range_start.max(0) as usize..range_end.max(0) as usize;
581
582        let (new_id_start, new_id_end) = if range_start >= 0 {
583            // We satisfied all requests from the freelist.
584            (0, 0)
585        } else {
586            // We need to allocate some new Entity IDs outside of the range of self.meta.
587            //
588            // `range_start` covers some negative territory, e.g. `-3..6`.
589            // Since the nonnegative values `0..6` are handled by the freelist, that
590            // means we need to handle the negative range here.
591            //
592            // In this example, we truncate the end to 0, leaving us with `-3..0`.
593            // Then we negate these values to indicate how far beyond the end of `meta.end()`
594            // to go, yielding `meta.len()+0 .. meta.len()+3`.
595            let base = self.meta.len() as IdCursor;
596
597            let new_id_end = u32::try_from(base - range_start).expect("too many entities");
598
599            // `new_id_end` is in range, so no need to check `start`.
600            let new_id_start = (base - range_end.min(0)) as u32;
601
602            (new_id_start, new_id_end)
603        };
604
605        ReserveEntitiesIterator {
606            meta: &self.meta[..],
607            freelist_indices: self.pending[freelist_range].iter(),
608            new_indices: new_id_start..new_id_end,
609        }
610    }
611
612    /// Reserve one entity ID concurrently.
613    ///
614    /// Equivalent to `self.reserve_entities(1).next().unwrap()`, but more efficient.
615    pub fn reserve_entity(&self) -> Entity {
616        let n = self.free_cursor.fetch_sub(1, Ordering::Relaxed);
617        if n > 0 {
618            // Allocate from the freelist.
619            let index = self.pending[(n - 1) as usize];
620            Entity::from_raw_and_generation(index, self.meta[index as usize].generation)
621        } else {
622            // Grab a new ID, outside the range of `meta.len()`. `flush()` must
623            // eventually be called to make it valid.
624            //
625            // As `self.free_cursor` goes more and more negative, we return IDs farther
626            // and farther beyond `meta.len()`.
627            Entity::from_raw(
628                u32::try_from(self.meta.len() as IdCursor - n).expect("too many entities"),
629            )
630        }
631    }
632
633    /// Check that we do not have pending work requiring `flush()` to be called.
634    fn verify_flushed(&mut self) {
635        debug_assert!(
636            !self.needs_flush(),
637            "flush() needs to be called before this operation is legal"
638        );
639    }
640
641    /// Allocate an entity ID directly.
642    pub fn alloc(&mut self) -> Entity {
643        self.verify_flushed();
644        self.len += 1;
645        if let Some(index) = self.pending.pop() {
646            let new_free_cursor = self.pending.len() as IdCursor;
647            *self.free_cursor.get_mut() = new_free_cursor;
648            Entity::from_raw_and_generation(index, self.meta[index as usize].generation)
649        } else {
650            let index = u32::try_from(self.meta.len()).expect("too many entities");
651            self.meta.push(EntityMeta::EMPTY);
652            Entity::from_raw(index)
653        }
654    }
655
656    /// Allocate a specific entity ID, overwriting its generation.
657    ///
658    /// Returns the location of the entity currently using the given ID, if any. Location should be
659    /// written immediately.
660    pub fn alloc_at(&mut self, entity: Entity) -> Option<EntityLocation> {
661        self.verify_flushed();
662
663        let loc = if entity.index() as usize >= self.meta.len() {
664            self.pending
665                .extend((self.meta.len() as u32)..entity.index());
666            let new_free_cursor = self.pending.len() as IdCursor;
667            *self.free_cursor.get_mut() = new_free_cursor;
668            self.meta
669                .resize(entity.index() as usize + 1, EntityMeta::EMPTY);
670            self.len += 1;
671            None
672        } else if let Some(index) = self.pending.iter().position(|item| *item == entity.index()) {
673            self.pending.swap_remove(index);
674            let new_free_cursor = self.pending.len() as IdCursor;
675            *self.free_cursor.get_mut() = new_free_cursor;
676            self.len += 1;
677            None
678        } else {
679            Some(mem::replace(
680                &mut self.meta[entity.index() as usize].location,
681                EntityMeta::EMPTY.location,
682            ))
683        };
684
685        self.meta[entity.index() as usize].generation = entity.generation;
686
687        loc
688    }
689
690    /// Allocate a specific entity ID, overwriting its generation.
691    ///
692    /// Returns the location of the entity currently using the given ID, if any.
693    pub(crate) fn alloc_at_without_replacement(
694        &mut self,
695        entity: Entity,
696    ) -> AllocAtWithoutReplacement {
697        self.verify_flushed();
698
699        let result = if entity.index() as usize >= self.meta.len() {
700            self.pending
701                .extend((self.meta.len() as u32)..entity.index());
702            let new_free_cursor = self.pending.len() as IdCursor;
703            *self.free_cursor.get_mut() = new_free_cursor;
704            self.meta
705                .resize(entity.index() as usize + 1, EntityMeta::EMPTY);
706            self.len += 1;
707            AllocAtWithoutReplacement::DidNotExist
708        } else if let Some(index) = self.pending.iter().position(|item| *item == entity.index()) {
709            self.pending.swap_remove(index);
710            let new_free_cursor = self.pending.len() as IdCursor;
711            *self.free_cursor.get_mut() = new_free_cursor;
712            self.len += 1;
713            AllocAtWithoutReplacement::DidNotExist
714        } else {
715            let current_meta = &self.meta[entity.index() as usize];
716            if current_meta.location.archetype_id == ArchetypeId::INVALID {
717                AllocAtWithoutReplacement::DidNotExist
718            } else if current_meta.generation == entity.generation {
719                AllocAtWithoutReplacement::Exists(current_meta.location)
720            } else {
721                return AllocAtWithoutReplacement::ExistsWithWrongGeneration;
722            }
723        };
724
725        self.meta[entity.index() as usize].generation = entity.generation;
726        result
727    }
728
729    /// Destroy an entity, allowing it to be reused.
730    ///
731    /// Must not be called while reserved entities are awaiting `flush()`.
732    pub fn free(&mut self, entity: Entity) -> Option<EntityLocation> {
733        self.verify_flushed();
734
735        let meta = &mut self.meta[entity.index() as usize];
736        if meta.generation != entity.generation {
737            return None;
738        }
739
740        meta.generation = IdentifierMask::inc_masked_high_by(meta.generation, 1);
741
742        if meta.generation == NonZero::<u32>::MIN {
743            warn!(
744                "Entity({}) generation wrapped on Entities::free, aliasing may occur",
745                entity.index
746            );
747        }
748
749        let loc = mem::replace(&mut meta.location, EntityMeta::EMPTY.location);
750
751        self.pending.push(entity.index());
752
753        let new_free_cursor = self.pending.len() as IdCursor;
754        *self.free_cursor.get_mut() = new_free_cursor;
755        self.len -= 1;
756        Some(loc)
757    }
758
759    /// Ensure at least `n` allocations can succeed without reallocating.
760    #[allow(clippy::unnecessary_fallible_conversions)] // Because `IdCursor::try_from` may fail on 32-bit platforms.
761    pub fn reserve(&mut self, additional: u32) {
762        self.verify_flushed();
763
764        let freelist_size = *self.free_cursor.get_mut();
765        let shortfall = IdCursor::try_from(additional)
766            .expect("64-bit atomic operations are not supported on this platform.")
767            - freelist_size;
768        if shortfall > 0 {
769            self.meta.reserve(shortfall as usize);
770        }
771    }
772
773    /// Returns true if the [`Entities`] contains [`entity`](Entity).
774    // This will return false for entities which have been freed, even if
775    // not reallocated since the generation is incremented in `free`
776    pub fn contains(&self, entity: Entity) -> bool {
777        self.resolve_from_id(entity.index())
778            .map_or(false, |e| e.generation() == entity.generation())
779    }
780
781    /// Clears all [`Entity`] from the World.
782    pub fn clear(&mut self) {
783        self.meta.clear();
784        self.pending.clear();
785        *self.free_cursor.get_mut() = 0;
786        self.len = 0;
787    }
788
789    /// Returns the location of an [`Entity`].
790    /// Note: for pending entities, returns `Some(EntityLocation::INVALID)`.
791    #[inline]
792    pub fn get(&self, entity: Entity) -> Option<EntityLocation> {
793        if let Some(meta) = self.meta.get(entity.index() as usize) {
794            if meta.generation != entity.generation
795                || meta.location.archetype_id == ArchetypeId::INVALID
796            {
797                return None;
798            }
799            Some(meta.location)
800        } else {
801            None
802        }
803    }
804
805    /// Updates the location of an [`Entity`]. This must be called when moving the components of
806    /// the entity around in storage.
807    ///
808    /// # Safety
809    ///  - `index` must be a valid entity index.
810    ///  - `location` must be valid for the entity at `index` or immediately made valid afterwards
811    ///    before handing control to unknown code.
812    #[inline]
813    pub(crate) unsafe fn set(&mut self, index: u32, location: EntityLocation) {
814        // SAFETY: Caller guarantees that `index` a valid entity index
815        let meta = unsafe { self.meta.get_unchecked_mut(index as usize) };
816        meta.location = location;
817    }
818
819    /// Increments the `generation` of a freed [`Entity`]. The next entity ID allocated with this
820    /// `index` will count `generation` starting from the prior `generation` + the specified
821    /// value + 1.
822    ///
823    /// Does nothing if no entity with this `index` has been allocated yet.
824    pub(crate) fn reserve_generations(&mut self, index: u32, generations: u32) -> bool {
825        if (index as usize) >= self.meta.len() {
826            return false;
827        }
828
829        let meta = &mut self.meta[index as usize];
830        if meta.location.archetype_id == ArchetypeId::INVALID {
831            meta.generation = IdentifierMask::inc_masked_high_by(meta.generation, generations);
832            true
833        } else {
834            false
835        }
836    }
837
838    /// Get the [`Entity`] with a given id, if it exists in this [`Entities`] collection
839    /// Returns `None` if this [`Entity`] is outside of the range of currently reserved Entities
840    ///
841    /// Note: This method may return [`Entities`](Entity) which are currently free
842    /// Note that [`contains`](Entities::contains) will correctly return false for freed
843    /// entities, since it checks the generation
844    pub fn resolve_from_id(&self, index: u32) -> Option<Entity> {
845        let idu = index as usize;
846        if let Some(&EntityMeta { generation, .. }) = self.meta.get(idu) {
847            Some(Entity::from_raw_and_generation(index, generation))
848        } else {
849            // `id` is outside of the meta list - check whether it is reserved but not yet flushed.
850            let free_cursor = self.free_cursor.load(Ordering::Relaxed);
851            // If this entity was manually created, then free_cursor might be positive
852            // Returning None handles that case correctly
853            let num_pending = usize::try_from(-free_cursor).ok()?;
854            (idu < self.meta.len() + num_pending).then_some(Entity::from_raw(index))
855        }
856    }
857
858    fn needs_flush(&mut self) -> bool {
859        *self.free_cursor.get_mut() != self.pending.len() as IdCursor
860    }
861
862    /// Allocates space for entities previously reserved with [`reserve_entity`](Entities::reserve_entity) or
863    /// [`reserve_entities`](Entities::reserve_entities), then initializes each one using the supplied function.
864    ///
865    /// # Safety
866    /// Flush _must_ set the entity location to the correct [`ArchetypeId`] for the given [`Entity`]
867    /// each time init is called. This _can_ be [`ArchetypeId::INVALID`], provided the [`Entity`]
868    /// has not been assigned to an [`Archetype`][crate::archetype::Archetype].
869    ///
870    /// Note: freshly-allocated entities (ones which don't come from the pending list) are guaranteed
871    /// to be initialized with the invalid archetype.
872    pub unsafe fn flush(&mut self, mut init: impl FnMut(Entity, &mut EntityLocation)) {
873        let free_cursor = self.free_cursor.get_mut();
874        let current_free_cursor = *free_cursor;
875
876        let new_free_cursor = if current_free_cursor >= 0 {
877            current_free_cursor as usize
878        } else {
879            let old_meta_len = self.meta.len();
880            let new_meta_len = old_meta_len + -current_free_cursor as usize;
881            self.meta.resize(new_meta_len, EntityMeta::EMPTY);
882            self.len += -current_free_cursor as u32;
883            for (index, meta) in self.meta.iter_mut().enumerate().skip(old_meta_len) {
884                init(
885                    Entity::from_raw_and_generation(index as u32, meta.generation),
886                    &mut meta.location,
887                );
888            }
889
890            *free_cursor = 0;
891            0
892        };
893
894        self.len += (self.pending.len() - new_free_cursor) as u32;
895        for index in self.pending.drain(new_free_cursor..) {
896            let meta = &mut self.meta[index as usize];
897            init(
898                Entity::from_raw_and_generation(index, meta.generation),
899                &mut meta.location,
900            );
901        }
902    }
903
904    /// Flushes all reserved entities to an "invalid" state. Attempting to retrieve them will return `None`
905    /// unless they are later populated with a valid archetype.
906    pub fn flush_as_invalid(&mut self) {
907        // SAFETY: as per `flush` safety docs, the archetype id can be set to [`ArchetypeId::INVALID`] if
908        // the [`Entity`] has not been assigned to an [`Archetype`][crate::archetype::Archetype], which is the case here
909        unsafe {
910            self.flush(|_entity, location| {
911                location.archetype_id = ArchetypeId::INVALID;
912            });
913        }
914    }
915
916    /// # Safety
917    ///
918    /// This function is safe if and only if the world this Entities is on has no entities.
919    pub unsafe fn flush_and_reserve_invalid_assuming_no_entities(&mut self, count: usize) {
920        let free_cursor = self.free_cursor.get_mut();
921        *free_cursor = 0;
922        self.meta.reserve(count);
923        // SAFETY: The EntityMeta struct only contains integers, and it is valid to have all bytes set to u8::MAX
924        unsafe {
925            self.meta.as_mut_ptr().write_bytes(u8::MAX, count);
926        }
927        // SAFETY: We have reserved `count` elements above and we have initialized values from index 0 to `count`.
928        unsafe {
929            self.meta.set_len(count);
930        }
931
932        self.len = count as u32;
933    }
934
935    /// The count of all entities in the [`World`] that have ever been allocated
936    /// including the entities that are currently freed.
937    ///
938    /// This does not include entities that have been reserved but have never been
939    /// allocated yet.
940    ///
941    /// [`World`]: crate::world::World
942    #[inline]
943    pub fn total_count(&self) -> usize {
944        self.meta.len()
945    }
946
947    /// The count of currently allocated entities.
948    #[inline]
949    pub fn len(&self) -> u32 {
950        self.len
951    }
952
953    /// Checks if any entity is currently active.
954    #[inline]
955    pub fn is_empty(&self) -> bool {
956        self.len == 0
957    }
958}
959
960// This type is repr(C) to ensure that the layout and values within it can be safe to fully fill
961// with u8::MAX, as required by [`Entities::flush_and_reserve_invalid_assuming_no_entities`].
962// Safety:
963// This type must not contain any pointers at any level, and be safe to fully fill with u8::MAX.
964/// Metadata for an [`Entity`].
965#[derive(Copy, Clone, Debug)]
966#[repr(C)]
967struct EntityMeta {
968    /// The current generation of the [`Entity`].
969    pub generation: NonZero<u32>,
970    /// The current location of the [`Entity`]
971    pub location: EntityLocation,
972}
973
974impl EntityMeta {
975    /// meta for **pending entity**
976    const EMPTY: EntityMeta = EntityMeta {
977        generation: NonZero::<u32>::MIN,
978        location: EntityLocation::INVALID,
979    };
980}
981
982// This type is repr(C) to ensure that the layout and values within it can be safe to fully fill
983// with u8::MAX, as required by [`Entities::flush_and_reserve_invalid_assuming_no_entities`].
984// SAFETY:
985// This type must not contain any pointers at any level, and be safe to fully fill with u8::MAX.
986/// A location of an entity in an archetype.
987#[derive(Copy, Clone, Debug, PartialEq)]
988#[repr(C)]
989pub struct EntityLocation {
990    /// The ID of the [`Archetype`] the [`Entity`] belongs to.
991    ///
992    /// [`Archetype`]: crate::archetype::Archetype
993    pub archetype_id: ArchetypeId,
994
995    /// The index of the [`Entity`] within its [`Archetype`].
996    ///
997    /// [`Archetype`]: crate::archetype::Archetype
998    pub archetype_row: ArchetypeRow,
999
1000    /// The ID of the [`Table`] the [`Entity`] belongs to.
1001    ///
1002    /// [`Table`]: crate::storage::Table
1003    pub table_id: TableId,
1004
1005    /// The index of the [`Entity`] within its [`Table`].
1006    ///
1007    /// [`Table`]: crate::storage::Table
1008    pub table_row: TableRow,
1009}
1010
1011impl EntityLocation {
1012    /// location for **pending entity** and **invalid entity**
1013    const INVALID: EntityLocation = EntityLocation {
1014        archetype_id: ArchetypeId::INVALID,
1015        archetype_row: ArchetypeRow::INVALID,
1016        table_id: TableId::INVALID,
1017        table_row: TableRow::INVALID,
1018    };
1019}
1020
1021#[cfg(test)]
1022mod tests {
1023    use super::*;
1024
1025    #[test]
1026    fn entity_niche_optimization() {
1027        assert_eq!(size_of::<Entity>(), size_of::<Option<Entity>>());
1028    }
1029
1030    #[test]
1031    fn entity_bits_roundtrip() {
1032        // Generation cannot be greater than 0x7FFF_FFFF else it will be an invalid Entity id
1033        let e =
1034            Entity::from_raw_and_generation(0xDEADBEEF, NonZero::<u32>::new(0x5AADF00D).unwrap());
1035        assert_eq!(Entity::from_bits(e.to_bits()), e);
1036    }
1037
1038    #[test]
1039    fn reserve_entity_len() {
1040        let mut e = Entities::new();
1041        e.reserve_entity();
1042        // SAFETY: entity_location is left invalid
1043        unsafe { e.flush(|_, _| {}) };
1044        assert_eq!(e.len(), 1);
1045    }
1046
1047    #[test]
1048    fn get_reserved_and_invalid() {
1049        let mut entities = Entities::new();
1050        let e = entities.reserve_entity();
1051        assert!(entities.contains(e));
1052        assert!(entities.get(e).is_none());
1053
1054        // SAFETY: entity_location is left invalid
1055        unsafe {
1056            entities.flush(|_entity, _location| {
1057                // do nothing ... leaving entity location invalid
1058            });
1059        };
1060
1061        assert!(entities.contains(e));
1062        assert!(entities.get(e).is_none());
1063    }
1064
1065    #[test]
1066    fn entity_const() {
1067        const C1: Entity = Entity::from_raw(42);
1068        assert_eq!(42, C1.index());
1069        assert_eq!(1, C1.generation());
1070
1071        const C2: Entity = Entity::from_bits(0x0000_00ff_0000_00cc);
1072        assert_eq!(0x0000_00cc, C2.index());
1073        assert_eq!(0x0000_00ff, C2.generation());
1074
1075        const C3: u32 = Entity::from_raw(33).index();
1076        assert_eq!(33, C3);
1077
1078        const C4: u32 = Entity::from_bits(0x00dd_00ff_0000_0000).generation();
1079        assert_eq!(0x00dd_00ff, C4);
1080    }
1081
1082    #[test]
1083    fn reserve_generations() {
1084        let mut entities = Entities::new();
1085        let entity = entities.alloc();
1086        entities.free(entity);
1087
1088        assert!(entities.reserve_generations(entity.index(), 1));
1089    }
1090
1091    #[test]
1092    fn reserve_generations_and_alloc() {
1093        const GENERATIONS: u32 = 10;
1094
1095        let mut entities = Entities::new();
1096        let entity = entities.alloc();
1097        entities.free(entity);
1098
1099        assert!(entities.reserve_generations(entity.index(), GENERATIONS));
1100
1101        // The very next entity allocated should be a further generation on the same index
1102        let next_entity = entities.alloc();
1103        assert_eq!(next_entity.index(), entity.index());
1104        assert!(next_entity.generation() > entity.generation() + GENERATIONS);
1105    }
1106
1107    #[test]
1108    #[allow(clippy::nonminimal_bool)] // This is intentionally testing `lt` and `ge` as separate functions.
1109    fn entity_comparison() {
1110        assert_eq!(
1111            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()),
1112            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1113        );
1114        assert_ne!(
1115            Entity::from_raw_and_generation(123, NonZero::<u32>::new(789).unwrap()),
1116            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1117        );
1118        assert_ne!(
1119            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()),
1120            Entity::from_raw_and_generation(123, NonZero::<u32>::new(789).unwrap())
1121        );
1122        assert_ne!(
1123            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()),
1124            Entity::from_raw_and_generation(456, NonZero::<u32>::new(123).unwrap())
1125        );
1126
1127        // ordering is by generation then by index
1128
1129        assert!(
1130            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1131                >= Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1132        );
1133        assert!(
1134            Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1135                <= Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1136        );
1137        assert!(
1138            !(Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1139                < Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()))
1140        );
1141        assert!(
1142            !(Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1143                > Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()))
1144        );
1145
1146        assert!(
1147            Entity::from_raw_and_generation(9, NonZero::<u32>::new(1).unwrap())
1148                < Entity::from_raw_and_generation(1, NonZero::<u32>::new(9).unwrap())
1149        );
1150        assert!(
1151            Entity::from_raw_and_generation(1, NonZero::<u32>::new(9).unwrap())
1152                > Entity::from_raw_and_generation(9, NonZero::<u32>::new(1).unwrap())
1153        );
1154
1155        assert!(
1156            Entity::from_raw_and_generation(1, NonZero::<u32>::new(1).unwrap())
1157                < Entity::from_raw_and_generation(2, NonZero::<u32>::new(1).unwrap())
1158        );
1159        assert!(
1160            Entity::from_raw_and_generation(1, NonZero::<u32>::new(1).unwrap())
1161                <= Entity::from_raw_and_generation(2, NonZero::<u32>::new(1).unwrap())
1162        );
1163        assert!(
1164            Entity::from_raw_and_generation(2, NonZero::<u32>::new(2).unwrap())
1165                > Entity::from_raw_and_generation(1, NonZero::<u32>::new(2).unwrap())
1166        );
1167        assert!(
1168            Entity::from_raw_and_generation(2, NonZero::<u32>::new(2).unwrap())
1169                >= Entity::from_raw_and_generation(1, NonZero::<u32>::new(2).unwrap())
1170        );
1171    }
1172
1173    // Feel free to change this test if needed, but it seemed like an important
1174    // part of the best-case performance changes in PR#9903.
1175    #[test]
1176    fn entity_hash_keeps_similar_ids_together() {
1177        use core::hash::BuildHasher;
1178        let hash = EntityHash;
1179
1180        let first_id = 0xC0FFEE << 8;
1181        let first_hash = hash.hash_one(Entity::from_raw(first_id));
1182
1183        for i in 1..=255 {
1184            let id = first_id + i;
1185            let hash = hash.hash_one(Entity::from_raw(id));
1186            assert_eq!(hash.wrapping_sub(first_hash) as u32, i);
1187        }
1188    }
1189
1190    #[test]
1191    fn entity_hash_id_bitflip_affects_high_7_bits() {
1192        use core::hash::BuildHasher;
1193
1194        let hash = EntityHash;
1195
1196        let first_id = 0xC0FFEE;
1197        let first_hash = hash.hash_one(Entity::from_raw(first_id)) >> 57;
1198
1199        for bit in 0..u32::BITS {
1200            let id = first_id ^ (1 << bit);
1201            let hash = hash.hash_one(Entity::from_raw(id)) >> 57;
1202            assert_ne!(hash, first_hash);
1203        }
1204    }
1205
1206    #[test]
1207    fn entity_debug() {
1208        let entity = Entity::from_raw(42);
1209        let string = format!("{:?}", entity);
1210        assert_eq!(string, "42v1#4294967338");
1211
1212        let entity = Entity::PLACEHOLDER;
1213        let string = format!("{:?}", entity);
1214        assert_eq!(string, "PLACEHOLDER");
1215    }
1216
1217    #[test]
1218    fn entity_display() {
1219        let entity = Entity::from_raw(42);
1220        let string = format!("{}", entity);
1221        assert_eq!(string, "42v1");
1222
1223        let entity = Entity::PLACEHOLDER;
1224        let string = format!("{}", entity);
1225        assert_eq!(string, "PLACEHOLDER");
1226    }
1227}