bevy_ecs/
bundle.rs

1//! Types for handling [`Bundle`]s.
2//!
3//! This module contains the [`Bundle`] trait and some other helper types.
4
5pub use bevy_ecs_macros::Bundle;
6
7use crate::{
8    archetype::{
9        Archetype, ArchetypeAfterBundleInsert, ArchetypeId, Archetypes, BundleComponentStatus,
10        ComponentStatus, SpawnBundleStatus,
11    },
12    change_detection::MaybeLocation,
13    component::{
14        Component, ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor,
15        RequiredComponents, StorageType, Tick,
16    },
17    entity::{Entities, Entity, EntityLocation},
18    observer::Observers,
19    prelude::World,
20    query::DebugCheckedUnwrap,
21    relationship::RelationshipHookMode,
22    storage::{SparseSetIndex, SparseSets, Storages, Table, TableRow},
23    world::{unsafe_world_cell::UnsafeWorldCell, EntityWorldMut, ON_ADD, ON_INSERT, ON_REPLACE},
24};
25use alloc::{boxed::Box, vec, vec::Vec};
26use bevy_platform::collections::{HashMap, HashSet};
27use bevy_ptr::{ConstNonNull, OwningPtr};
28use bevy_utils::TypeIdMap;
29use core::{any::TypeId, ptr::NonNull};
30use variadics_please::all_tuples;
31
32/// The `Bundle` trait enables insertion and removal of [`Component`]s from an entity.
33///
34/// Implementers of the `Bundle` trait are called 'bundles'.
35///
36/// Each bundle represents a static set of [`Component`] types.
37/// Currently, bundles can only contain one of each [`Component`], and will
38/// panic once initialized if this is not met.
39///
40/// ## Insertion
41///
42/// The primary use for bundles is to add a useful collection of components to an entity.
43///
44/// Adding a value of bundle to an entity will add the components from the set it
45/// represents to the entity.
46/// The values of these components are taken from the bundle.
47/// If an entity already had one of these components, the entity's original component value
48/// will be overwritten.
49///
50/// Importantly, bundles are only their constituent set of components.
51/// You **should not** use bundles as a unit of behavior.
52/// The behavior of your app can only be considered in terms of components, as systems,
53/// which drive the behavior of a `bevy` application, operate on combinations of
54/// components.
55///
56/// This rule is also important because multiple bundles may contain the same component type,
57/// calculated in different ways — adding both of these bundles to one entity
58/// would create incoherent behavior.
59/// This would be unexpected if bundles were treated as an abstraction boundary, as
60/// the abstraction would be unmaintainable for these cases.
61///
62/// For this reason, there is intentionally no [`Query`] to match whether an entity
63/// contains the components of a bundle.
64/// Queries should instead only select the components they logically operate on.
65///
66/// ## Removal
67///
68/// Bundles are also used when removing components from an entity.
69///
70/// Removing a bundle from an entity will remove any of its components attached
71/// to the entity from the entity.
72/// That is, if the entity does not have all the components of the bundle, those
73/// which are present will be removed.
74///
75/// # Implementers
76///
77/// Every type which implements [`Component`] also implements `Bundle`, since
78/// [`Component`] types can be added to or removed from an entity.
79///
80/// Additionally, [Tuples](`tuple`) of bundles are also [`Bundle`] (with up to 15 bundles).
81/// These bundles contain the items of the 'inner' bundles.
82/// This is a convenient shorthand which is primarily used when spawning entities.
83///
84/// [`unit`], otherwise known as [`()`](`unit`), is a [`Bundle`] containing no components (since it
85/// can also be considered as the empty tuple).
86/// This can be useful for spawning large numbers of empty entities using
87/// [`World::spawn_batch`](crate::world::World::spawn_batch).
88///
89/// Tuple bundles can be nested, which can be used to create an anonymous bundle with more than
90/// 15 items.
91/// However, in most cases where this is required, the derive macro [`derive@Bundle`] should be
92/// used instead.
93/// The derived `Bundle` implementation contains the items of its fields, which all must
94/// implement `Bundle`.
95/// As explained above, this includes any [`Component`] type, and other derived bundles.
96///
97/// If you want to add `PhantomData` to your `Bundle` you have to mark it with `#[bundle(ignore)]`.
98/// ```
99/// # use std::marker::PhantomData;
100/// use bevy_ecs::{component::Component, bundle::Bundle};
101///
102/// #[derive(Component)]
103/// struct XPosition(i32);
104/// #[derive(Component)]
105/// struct YPosition(i32);
106///
107/// #[derive(Bundle)]
108/// struct PositionBundle {
109///     // A bundle can contain components
110///     x: XPosition,
111///     y: YPosition,
112/// }
113///
114/// // You have to implement `Default` for ignored field types in bundle structs.
115/// #[derive(Default)]
116/// struct Other(f32);
117///
118/// #[derive(Bundle)]
119/// struct NamedPointBundle<T: Send + Sync + 'static> {
120///     // Or other bundles
121///     a: PositionBundle,
122///     // In addition to more components
123///     z: PointName,
124///
125///     // when you need to use `PhantomData` you have to mark it as ignored
126///     #[bundle(ignore)]
127///     _phantom_data: PhantomData<T>
128/// }
129///
130/// #[derive(Component)]
131/// struct PointName(String);
132/// ```
133///
134/// # Safety
135///
136/// Manual implementations of this trait are unsupported.
137/// That is, there is no safe way to implement this trait, and you must not do so.
138/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
139///
140/// [`Query`]: crate::system::Query
141// Some safety points:
142// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
143// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
144// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
145//   [`Bundle::component_ids`].
146#[diagnostic::on_unimplemented(
147    message = "`{Self}` is not a `Bundle`",
148    label = "invalid `Bundle`",
149    note = "consider annotating `{Self}` with `#[derive(Component)]` or `#[derive(Bundle)]`"
150)]
151pub unsafe trait Bundle: DynamicBundle + Send + Sync + 'static {
152    /// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s
153    #[doc(hidden)]
154    fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId));
155
156    /// Gets this [`Bundle`]'s component ids. This will be [`None`] if the component has not been registered.
157    fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>));
158
159    /// Registers components that are required by the components in this [`Bundle`].
160    fn register_required_components(
161        _components: &mut ComponentsRegistrator,
162        _required_components: &mut RequiredComponents,
163    );
164}
165
166/// Creates a [`Bundle`] by taking it from internal storage.
167///
168/// # Safety
169///
170/// Manual implementations of this trait are unsupported.
171/// That is, there is no safe way to implement this trait, and you must not do so.
172/// If you want a type to implement [`Bundle`], you must use [`derive@Bundle`](derive@Bundle).
173///
174/// [`Query`]: crate::system::Query
175// Some safety points:
176// - [`Bundle::component_ids`] must return the [`ComponentId`] for each component type in the
177// bundle, in the _exact_ order that [`DynamicBundle::get_components`] is called.
178// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by
179//   [`Bundle::component_ids`].
180pub unsafe trait BundleFromComponents {
181    /// Calls `func`, which should return data for each component in the bundle, in the order of
182    /// this bundle's [`Component`]s
183    ///
184    /// # Safety
185    /// Caller must return data for each component in the bundle, in the order of this bundle's
186    /// [`Component`]s
187    #[doc(hidden)]
188    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
189    where
190        // Ensure that the `OwningPtr` is used correctly
191        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
192        Self: Sized;
193}
194
195/// The parts from [`Bundle`] that don't require statically knowing the components of the bundle.
196pub trait DynamicBundle {
197    /// An operation on the entity that happens _after_ inserting this bundle.
198    type Effect: BundleEffect;
199    // SAFETY:
200    // The `StorageType` argument passed into [`Bundle::get_components`] must be correct for the
201    // component being fetched.
202    //
203    /// Calls `func` on each value, in the order of this bundle's [`Component`]s. This passes
204    /// ownership of the component values to `func`.
205    #[doc(hidden)]
206    fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect;
207}
208
209/// An operation on an [`Entity`] that occurs _after_ inserting the [`Bundle`] that defined this bundle effect.
210/// The order of operations is:
211///
212/// 1. The [`Bundle`] is inserted on the entity
213/// 2. Relevant Hooks are run for the insert, then Observers
214/// 3. The [`BundleEffect`] is run.
215///
216/// See [`DynamicBundle::Effect`].
217pub trait BundleEffect {
218    /// Applies this effect to the given `entity`.
219    fn apply(self, entity: &mut EntityWorldMut);
220}
221
222// SAFETY:
223// - `Bundle::component_ids` calls `ids` for C's component id (and nothing else)
224// - `Bundle::get_components` is called exactly once for C and passes the component's storage type based on its associated constant.
225unsafe impl<C: Component> Bundle for C {
226    fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId)) {
227        ids(components.register_component::<C>());
228    }
229
230    fn register_required_components(
231        components: &mut ComponentsRegistrator,
232        required_components: &mut RequiredComponents,
233    ) {
234        let component_id = components.register_component::<C>();
235        <C as Component>::register_required_components(
236            component_id,
237            components,
238            required_components,
239            0,
240            &mut Vec::new(),
241        );
242    }
243
244    fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)) {
245        ids(components.get_id(TypeId::of::<C>()));
246    }
247}
248
249// SAFETY:
250// - `Bundle::from_components` calls `func` exactly once for C, which is the exact value returned by `Bundle::component_ids`.
251unsafe impl<C: Component> BundleFromComponents for C {
252    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
253    where
254        // Ensure that the `OwningPtr` is used correctly
255        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
256        Self: Sized,
257    {
258        let ptr = func(ctx);
259        // Safety: The id given in `component_ids` is for `Self`
260        unsafe { ptr.read() }
261    }
262}
263
264impl<C: Component> DynamicBundle for C {
265    type Effect = ();
266    #[inline]
267    fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect {
268        OwningPtr::make(self, |ptr| func(C::STORAGE_TYPE, ptr));
269    }
270}
271
272macro_rules! tuple_impl {
273    ($(#[$meta:meta])* $($name: ident),*) => {
274        #[expect(
275            clippy::allow_attributes,
276            reason = "This is a tuple-related macro; as such, the lints below may not always apply."
277        )]
278        #[allow(
279            unused_mut,
280            unused_variables,
281            reason = "Zero-length tuples won't use any of the parameters."
282        )]
283        $(#[$meta])*
284        // SAFETY:
285        // - `Bundle::component_ids` calls `ids` for each component type in the
286        // bundle, in the exact order that `DynamicBundle::get_components` is called.
287        // - `Bundle::from_components` calls `func` exactly once for each `ComponentId` returned by `Bundle::component_ids`.
288        // - `Bundle::get_components` is called exactly once for each member. Relies on the above implementation to pass the correct
289        //   `StorageType` into the callback.
290        unsafe impl<$($name: Bundle),*> Bundle for ($($name,)*) {
291            fn component_ids(components: &mut ComponentsRegistrator,  ids: &mut impl FnMut(ComponentId)){
292                $(<$name as Bundle>::component_ids(components, ids);)*
293            }
294
295            fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>)){
296                $(<$name as Bundle>::get_component_ids(components, ids);)*
297            }
298
299            fn register_required_components(
300                components: &mut ComponentsRegistrator,
301                required_components: &mut RequiredComponents,
302            ) {
303                $(<$name as Bundle>::register_required_components(components, required_components);)*
304            }
305        }
306
307        #[expect(
308            clippy::allow_attributes,
309            reason = "This is a tuple-related macro; as such, the lints below may not always apply."
310        )]
311        #[allow(
312            unused_mut,
313            unused_variables,
314            reason = "Zero-length tuples won't use any of the parameters."
315        )]
316        $(#[$meta])*
317        // SAFETY:
318        // - `Bundle::component_ids` calls `ids` for each component type in the
319        // bundle, in the exact order that `DynamicBundle::get_components` is called.
320        // - `Bundle::from_components` calls `func` exactly once for each `ComponentId` returned by `Bundle::component_ids`.
321        // - `Bundle::get_components` is called exactly once for each member. Relies on the above implementation to pass the correct
322        //   `StorageType` into the callback.
323        unsafe impl<$($name: BundleFromComponents),*> BundleFromComponents for ($($name,)*) {
324            #[allow(
325                clippy::unused_unit,
326                reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
327            )]
328            unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
329            where
330                F: FnMut(&mut T) -> OwningPtr<'_>
331            {
332                #[allow(
333                    unused_unsafe,
334                    reason = "Zero-length tuples will not run anything in the unsafe block. Additionally, rewriting this to move the () outside of the unsafe would require putting the safety comment inside the tuple, hurting readability of the code."
335                )]
336                // SAFETY: Rust guarantees that tuple calls are evaluated 'left to right'.
337                // https://doc.rust-lang.org/reference/expressions.html#evaluation-order-of-operands
338                unsafe { ($(<$name as BundleFromComponents>::from_components(ctx, func),)*) }
339            }
340        }
341
342        #[expect(
343            clippy::allow_attributes,
344            reason = "This is a tuple-related macro; as such, the lints below may not always apply."
345        )]
346        #[allow(
347            unused_mut,
348            unused_variables,
349            reason = "Zero-length tuples won't use any of the parameters."
350        )]
351        $(#[$meta])*
352        impl<$($name: Bundle),*> DynamicBundle for ($($name,)*) {
353            type Effect = ($($name::Effect,)*);
354            #[allow(
355                clippy::unused_unit,
356                reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case."
357            )]
358            #[inline(always)]
359            fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect {
360                #[allow(
361                    non_snake_case,
362                    reason = "The names of these variables are provided by the caller, not by us."
363                )]
364                let ($(mut $name,)*) = self;
365                ($(
366                    $name.get_components(&mut *func),
367                )*)
368            }
369        }
370    }
371}
372
373all_tuples!(
374    #[doc(fake_variadic)]
375    tuple_impl,
376    0,
377    15,
378    B
379);
380
381/// A trait implemented for [`BundleEffect`] implementations that do nothing. This is used as a type constraint for
382/// [`Bundle`] APIs that do not / cannot run [`DynamicBundle::Effect`], such as "batch spawn" APIs.
383pub trait NoBundleEffect {}
384
385macro_rules! after_effect_impl {
386    ($($after_effect: ident),*) => {
387        #[expect(
388            clippy::allow_attributes,
389            reason = "This is a tuple-related macro; as such, the lints below may not always apply."
390        )]
391        impl<$($after_effect: BundleEffect),*> BundleEffect for ($($after_effect,)*) {
392            #[allow(
393                clippy::unused_unit,
394                reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case.")
395            ]
396            fn apply(self, _entity: &mut EntityWorldMut) {
397                #[allow(
398                    non_snake_case,
399                    reason = "The names of these variables are provided by the caller, not by us."
400                )]
401                let ($($after_effect,)*) = self;
402                $($after_effect.apply(_entity);)*
403            }
404        }
405
406        impl<$($after_effect: NoBundleEffect),*> NoBundleEffect for ($($after_effect,)*) { }
407    }
408}
409
410all_tuples!(after_effect_impl, 0, 15, P);
411
412/// For a specific [`World`], this stores a unique value identifying a type of a registered [`Bundle`].
413///
414/// [`World`]: crate::world::World
415#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
416pub struct BundleId(usize);
417
418impl BundleId {
419    /// Returns the index of the associated [`Bundle`] type.
420    ///
421    /// Note that this is unique per-world, and should not be reused across them.
422    #[inline]
423    pub fn index(self) -> usize {
424        self.0
425    }
426}
427
428impl SparseSetIndex for BundleId {
429    #[inline]
430    fn sparse_set_index(&self) -> usize {
431        self.index()
432    }
433
434    #[inline]
435    fn get_sparse_set_index(value: usize) -> Self {
436        Self(value)
437    }
438}
439
440/// What to do on insertion if a component already exists.
441#[derive(Clone, Copy, Eq, PartialEq)]
442pub enum InsertMode {
443    /// Any existing components of a matching type will be overwritten.
444    Replace,
445    /// Any existing components of a matching type will be left unchanged.
446    Keep,
447}
448
449/// Stores metadata associated with a specific type of [`Bundle`] for a given [`World`].
450///
451/// [`World`]: crate::world::World
452pub struct BundleInfo {
453    id: BundleId,
454    /// The list of all components contributed by the bundle (including Required Components). This is in
455    /// the order `[EXPLICIT_COMPONENTS][REQUIRED_COMPONENTS]`
456    ///
457    /// # Safety
458    /// Every ID in this list must be valid within the World that owns the [`BundleInfo`],
459    /// must have its storage initialized (i.e. columns created in tables, sparse set created),
460    /// and the range (0..`explicit_components_len`) must be in the same order as the source bundle
461    /// type writes its components in.
462    component_ids: Vec<ComponentId>,
463    required_components: Vec<RequiredComponentConstructor>,
464    explicit_components_len: usize,
465}
466
467impl BundleInfo {
468    /// Create a new [`BundleInfo`].
469    ///
470    /// # Safety
471    ///
472    /// Every ID in `component_ids` must be valid within the World that owns the `BundleInfo`
473    /// and must be in the same order as the source bundle type writes its components in.
474    unsafe fn new(
475        bundle_type_name: &'static str,
476        storages: &mut Storages,
477        components: &Components,
478        mut component_ids: Vec<ComponentId>,
479        id: BundleId,
480    ) -> BundleInfo {
481        // check for duplicates
482        let mut deduped = component_ids.clone();
483        deduped.sort_unstable();
484        deduped.dedup();
485        if deduped.len() != component_ids.len() {
486            // TODO: Replace with `Vec::partition_dedup` once https://github.com/rust-lang/rust/issues/54279 is stabilized
487            let mut seen = <HashSet<_>>::default();
488            let mut dups = Vec::new();
489            for id in component_ids {
490                if !seen.insert(id) {
491                    dups.push(id);
492                }
493            }
494
495            let names = dups
496                .into_iter()
497                .map(|id| {
498                    // SAFETY: the caller ensures component_id is valid.
499                    unsafe { components.get_info_unchecked(id).name() }
500                })
501                .collect::<Vec<_>>()
502                .join(", ");
503
504            panic!("Bundle {bundle_type_name} has duplicate components: {names}");
505        }
506
507        // handle explicit components
508        let explicit_components_len = component_ids.len();
509        let mut required_components = RequiredComponents::default();
510        for component_id in component_ids.iter().copied() {
511            // SAFETY: caller has verified that all ids are valid
512            let info = unsafe { components.get_info_unchecked(component_id) };
513            required_components.merge(info.required_components());
514            storages.prepare_component(info);
515        }
516        required_components.remove_explicit_components(&component_ids);
517
518        // handle required components
519        let required_components = required_components
520            .0
521            .into_iter()
522            .map(|(component_id, v)| {
523                // Safety: These ids came out of the passed `components`, so they must be valid.
524                let info = unsafe { components.get_info_unchecked(component_id) };
525                storages.prepare_component(info);
526                // This adds required components to the component_ids list _after_ using that list to remove explicitly provided
527                // components. This ordering is important!
528                component_ids.push(component_id);
529                v.constructor
530            })
531            .collect();
532
533        // SAFETY: The caller ensures that component_ids:
534        // - is valid for the associated world
535        // - has had its storage initialized
536        // - is in the same order as the source bundle type
537        BundleInfo {
538            id,
539            component_ids,
540            required_components,
541            explicit_components_len,
542        }
543    }
544
545    /// Returns a value identifying the associated [`Bundle`] type.
546    #[inline]
547    pub const fn id(&self) -> BundleId {
548        self.id
549    }
550
551    /// Returns the [ID](ComponentId) of each component explicitly defined in this bundle (ex: Required Components are excluded).
552    ///
553    /// For all components contributed by this bundle (including Required Components), see [`BundleInfo::contributed_components`]
554    #[inline]
555    pub fn explicit_components(&self) -> &[ComponentId] {
556        &self.component_ids[0..self.explicit_components_len]
557    }
558
559    /// Returns the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
560    /// explicitly provided by the bundle.
561    #[inline]
562    pub fn required_components(&self) -> &[ComponentId] {
563        &self.component_ids[self.explicit_components_len..]
564    }
565
566    /// Returns the [ID](ComponentId) of each component contributed by this bundle. This includes Required Components.
567    ///
568    /// For only components explicitly defined in this bundle, see [`BundleInfo::explicit_components`]
569    #[inline]
570    pub fn contributed_components(&self) -> &[ComponentId] {
571        &self.component_ids
572    }
573
574    /// Returns an iterator over the [ID](ComponentId) of each component explicitly defined in this bundle (ex: this excludes Required Components).
575    /// To iterate all components contributed by this bundle (including Required Components), see [`BundleInfo::iter_contributed_components`]
576    #[inline]
577    pub fn iter_explicit_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
578        self.explicit_components().iter().copied()
579    }
580
581    /// Returns an iterator over the [ID](ComponentId) of each component contributed by this bundle. This includes Required Components.
582    ///
583    /// To iterate only components explicitly defined in this bundle, see [`BundleInfo::iter_explicit_components`]
584    #[inline]
585    pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
586        self.component_ids.iter().copied()
587    }
588
589    /// Returns an iterator over the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
590    /// explicitly provided by the bundle.
591    pub fn iter_required_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
592        self.required_components().iter().copied()
593    }
594
595    /// This writes components from a given [`Bundle`] to the given entity.
596    ///
597    /// # Safety
598    ///
599    /// `bundle_component_status` must return the "correct" [`ComponentStatus`] for each component
600    /// in the [`Bundle`], with respect to the entity's original archetype (prior to the bundle being added).
601    ///
602    /// For example, if the original archetype already has `ComponentA` and `T` also has `ComponentA`, the status
603    /// should be `Existing`. If the original archetype does not have `ComponentA`, the status should be `Added`.
604    ///
605    /// When "inserting" a bundle into an existing entity, [`ArchetypeAfterBundleInsert`]
606    /// should be used, which will report `Added` vs `Existing` status based on the current archetype's structure.
607    ///
608    /// When spawning a bundle, [`SpawnBundleStatus`] can be used instead, which removes the need
609    /// to look up the [`ArchetypeAfterBundleInsert`] in the archetype graph, which requires
610    /// ownership of the entity's current archetype.
611    ///
612    /// `table` must be the "new" table for `entity`. `table_row` must have space allocated for the
613    /// `entity`, `bundle` must match this [`BundleInfo`]'s type
614    #[inline]
615    unsafe fn write_components<'a, T: DynamicBundle, S: BundleComponentStatus>(
616        &self,
617        table: &mut Table,
618        sparse_sets: &mut SparseSets,
619        bundle_component_status: &S,
620        required_components: impl Iterator<Item = &'a RequiredComponentConstructor>,
621        entity: Entity,
622        table_row: TableRow,
623        change_tick: Tick,
624        bundle: T,
625        insert_mode: InsertMode,
626        caller: MaybeLocation,
627    ) -> T::Effect {
628        // NOTE: get_components calls this closure on each component in "bundle order".
629        // bundle_info.component_ids are also in "bundle order"
630        let mut bundle_component = 0;
631        let after_effect = bundle.get_components(&mut |storage_type, component_ptr| {
632            let component_id = *self.component_ids.get_unchecked(bundle_component);
633            // SAFETY: bundle_component is a valid index for this bundle
634            let status = unsafe { bundle_component_status.get_status(bundle_component) };
635            match storage_type {
636                StorageType::Table => {
637                    let column =
638                        // SAFETY: If component_id is in self.component_ids, BundleInfo::new ensures that
639                        // the target table contains the component.
640                        unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
641                    match (status, insert_mode) {
642                        (ComponentStatus::Added, _) => {
643                            column.initialize(table_row, component_ptr, change_tick, caller);
644                        }
645                        (ComponentStatus::Existing, InsertMode::Replace) => {
646                            column.replace(table_row, component_ptr, change_tick, caller);
647                        }
648                        (ComponentStatus::Existing, InsertMode::Keep) => {
649                            if let Some(drop_fn) = table.get_drop_for(component_id) {
650                                drop_fn(component_ptr);
651                            }
652                        }
653                    }
654                }
655                StorageType::SparseSet => {
656                    let sparse_set =
657                        // SAFETY: If component_id is in self.component_ids, BundleInfo::new ensures that
658                        // a sparse set exists for the component.
659                        unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
660                    match (status, insert_mode) {
661                        (ComponentStatus::Added, _) | (_, InsertMode::Replace) => {
662                            sparse_set.insert(entity, component_ptr, change_tick, caller);
663                        }
664                        (ComponentStatus::Existing, InsertMode::Keep) => {
665                            if let Some(drop_fn) = sparse_set.get_drop() {
666                                drop_fn(component_ptr);
667                            }
668                        }
669                    }
670                }
671            }
672            bundle_component += 1;
673        });
674
675        for required_component in required_components {
676            required_component.initialize(
677                table,
678                sparse_sets,
679                change_tick,
680                table_row,
681                entity,
682                caller,
683            );
684        }
685
686        after_effect
687    }
688
689    /// Internal method to initialize a required component from an [`OwningPtr`]. This should ultimately be called
690    /// in the context of [`BundleInfo::write_components`], via [`RequiredComponentConstructor::initialize`].
691    ///
692    /// # Safety
693    ///
694    /// `component_ptr` must point to a required component value that matches the given `component_id`. The `storage_type` must match
695    /// the type associated with `component_id`. The `entity` and `table_row` must correspond to an entity with an uninitialized
696    /// component matching `component_id`.
697    ///
698    /// This method _should not_ be called outside of [`BundleInfo::write_components`].
699    /// For more information, read the [`BundleInfo::write_components`] safety docs.
700    /// This function inherits the safety requirements defined there.
701    pub(crate) unsafe fn initialize_required_component(
702        table: &mut Table,
703        sparse_sets: &mut SparseSets,
704        change_tick: Tick,
705        table_row: TableRow,
706        entity: Entity,
707        component_id: ComponentId,
708        storage_type: StorageType,
709        component_ptr: OwningPtr,
710        caller: MaybeLocation,
711    ) {
712        {
713            match storage_type {
714                StorageType::Table => {
715                    let column =
716                        // SAFETY: If component_id is in required_components, BundleInfo::new requires that
717                        // the target table contains the component.
718                        unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
719                    column.initialize(table_row, component_ptr, change_tick, caller);
720                }
721                StorageType::SparseSet => {
722                    let sparse_set =
723                        // SAFETY: If component_id is in required_components, BundleInfo::new requires that
724                        // a sparse set exists for the component.
725                        unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
726                    sparse_set.insert(entity, component_ptr, change_tick, caller);
727                }
728            }
729        }
730    }
731
732    /// Inserts a bundle into the given archetype and returns the resulting archetype.
733    /// This could be the same [`ArchetypeId`], in the event that inserting the given bundle
734    /// does not result in an [`Archetype`] change.
735    ///
736    /// Results are cached in the [`Archetype`] graph to avoid redundant work.
737    ///
738    /// # Safety
739    /// `components` must be the same components as passed in [`Self::new`]
740    pub(crate) unsafe fn insert_bundle_into_archetype(
741        &self,
742        archetypes: &mut Archetypes,
743        storages: &mut Storages,
744        components: &Components,
745        observers: &Observers,
746        archetype_id: ArchetypeId,
747    ) -> ArchetypeId {
748        if let Some(archetype_after_insert_id) = archetypes[archetype_id]
749            .edges()
750            .get_archetype_after_bundle_insert(self.id)
751        {
752            return archetype_after_insert_id;
753        }
754        let mut new_table_components = Vec::new();
755        let mut new_sparse_set_components = Vec::new();
756        let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
757        let mut added_required_components = Vec::new();
758        let mut added = Vec::new();
759        let mut existing = Vec::new();
760
761        let current_archetype = &mut archetypes[archetype_id];
762        for component_id in self.iter_explicit_components() {
763            if current_archetype.contains(component_id) {
764                bundle_status.push(ComponentStatus::Existing);
765                existing.push(component_id);
766            } else {
767                bundle_status.push(ComponentStatus::Added);
768                added.push(component_id);
769                // SAFETY: component_id exists
770                let component_info = unsafe { components.get_info_unchecked(component_id) };
771                match component_info.storage_type() {
772                    StorageType::Table => new_table_components.push(component_id),
773                    StorageType::SparseSet => new_sparse_set_components.push(component_id),
774                }
775            }
776        }
777
778        for (index, component_id) in self.iter_required_components().enumerate() {
779            if !current_archetype.contains(component_id) {
780                added_required_components.push(self.required_components[index].clone());
781                added.push(component_id);
782                // SAFETY: component_id exists
783                let component_info = unsafe { components.get_info_unchecked(component_id) };
784                match component_info.storage_type() {
785                    StorageType::Table => {
786                        new_table_components.push(component_id);
787                    }
788                    StorageType::SparseSet => {
789                        new_sparse_set_components.push(component_id);
790                    }
791                }
792            }
793        }
794
795        if new_table_components.is_empty() && new_sparse_set_components.is_empty() {
796            let edges = current_archetype.edges_mut();
797            // The archetype does not change when we insert this bundle.
798            edges.cache_archetype_after_bundle_insert(
799                self.id,
800                archetype_id,
801                bundle_status,
802                added_required_components,
803                added,
804                existing,
805            );
806            archetype_id
807        } else {
808            let table_id;
809            let table_components;
810            let sparse_set_components;
811            // The archetype changes when we insert this bundle. Prepare the new archetype and storages.
812            {
813                let current_archetype = &archetypes[archetype_id];
814                table_components = if new_table_components.is_empty() {
815                    // If there are no new table components, we can keep using this table.
816                    table_id = current_archetype.table_id();
817                    current_archetype.table_components().collect()
818                } else {
819                    new_table_components.extend(current_archetype.table_components());
820                    // Sort to ignore order while hashing.
821                    new_table_components.sort_unstable();
822                    // SAFETY: all component ids in `new_table_components` exist
823                    table_id = unsafe {
824                        storages
825                            .tables
826                            .get_id_or_insert(&new_table_components, components)
827                    };
828
829                    new_table_components
830                };
831
832                sparse_set_components = if new_sparse_set_components.is_empty() {
833                    current_archetype.sparse_set_components().collect()
834                } else {
835                    new_sparse_set_components.extend(current_archetype.sparse_set_components());
836                    // Sort to ignore order while hashing.
837                    new_sparse_set_components.sort_unstable();
838                    new_sparse_set_components
839                };
840            };
841            // SAFETY: ids in self must be valid
842            let new_archetype_id = archetypes.get_id_or_insert(
843                components,
844                observers,
845                table_id,
846                table_components,
847                sparse_set_components,
848            );
849            // Add an edge from the old archetype to the new archetype.
850            archetypes[archetype_id]
851                .edges_mut()
852                .cache_archetype_after_bundle_insert(
853                    self.id,
854                    new_archetype_id,
855                    bundle_status,
856                    added_required_components,
857                    added,
858                    existing,
859                );
860            new_archetype_id
861        }
862    }
863
864    /// Removes a bundle from the given archetype and returns the resulting archetype
865    /// (or `None` if the removal was invalid).
866    /// This could be the same [`ArchetypeId`], in the event that removing the given bundle
867    /// does not result in an [`Archetype`] change.
868    ///
869    /// Results are cached in the [`Archetype`] graph to avoid redundant work.
870    ///
871    /// If `intersection` is false, attempting to remove a bundle with components not contained in the
872    /// current archetype will fail, returning `None`.
873    ///
874    /// If `intersection` is true, components in the bundle but not in the current archetype
875    /// will be ignored.
876    ///
877    /// # Safety
878    /// `archetype_id` must exist and components in `bundle_info` must exist
879    pub(crate) unsafe fn remove_bundle_from_archetype(
880        &self,
881        archetypes: &mut Archetypes,
882        storages: &mut Storages,
883        components: &Components,
884        observers: &Observers,
885        archetype_id: ArchetypeId,
886        intersection: bool,
887    ) -> Option<ArchetypeId> {
888        // Check the archetype graph to see if the bundle has been
889        // removed from this archetype in the past.
890        let archetype_after_remove_result = {
891            let edges = archetypes[archetype_id].edges();
892            if intersection {
893                edges.get_archetype_after_bundle_remove(self.id())
894            } else {
895                edges.get_archetype_after_bundle_take(self.id())
896            }
897        };
898        let result = if let Some(result) = archetype_after_remove_result {
899            // This bundle removal result is cached. Just return that!
900            result
901        } else {
902            let mut next_table_components;
903            let mut next_sparse_set_components;
904            let next_table_id;
905            {
906                let current_archetype = &mut archetypes[archetype_id];
907                let mut removed_table_components = Vec::new();
908                let mut removed_sparse_set_components = Vec::new();
909                for component_id in self.iter_explicit_components() {
910                    if current_archetype.contains(component_id) {
911                        // SAFETY: bundle components were already initialized by bundles.get_info
912                        let component_info = unsafe { components.get_info_unchecked(component_id) };
913                        match component_info.storage_type() {
914                            StorageType::Table => removed_table_components.push(component_id),
915                            StorageType::SparseSet => {
916                                removed_sparse_set_components.push(component_id);
917                            }
918                        }
919                    } else if !intersection {
920                        // A component in the bundle was not present in the entity's archetype, so this
921                        // removal is invalid. Cache the result in the archetype graph.
922                        current_archetype
923                            .edges_mut()
924                            .cache_archetype_after_bundle_take(self.id(), None);
925                        return None;
926                    }
927                }
928
929                // Sort removed components so we can do an efficient "sorted remove".
930                // Archetype components are already sorted.
931                removed_table_components.sort_unstable();
932                removed_sparse_set_components.sort_unstable();
933                next_table_components = current_archetype.table_components().collect();
934                next_sparse_set_components = current_archetype.sparse_set_components().collect();
935                sorted_remove(&mut next_table_components, &removed_table_components);
936                sorted_remove(
937                    &mut next_sparse_set_components,
938                    &removed_sparse_set_components,
939                );
940
941                next_table_id = if removed_table_components.is_empty() {
942                    current_archetype.table_id()
943                } else {
944                    // SAFETY: all components in next_table_components exist
945                    unsafe {
946                        storages
947                            .tables
948                            .get_id_or_insert(&next_table_components, components)
949                    }
950                };
951            }
952
953            let new_archetype_id = archetypes.get_id_or_insert(
954                components,
955                observers,
956                next_table_id,
957                next_table_components,
958                next_sparse_set_components,
959            );
960            Some(new_archetype_id)
961        };
962        let current_archetype = &mut archetypes[archetype_id];
963        // Cache the result in an edge.
964        if intersection {
965            current_archetype
966                .edges_mut()
967                .cache_archetype_after_bundle_remove(self.id(), result);
968        } else {
969            current_archetype
970                .edges_mut()
971                .cache_archetype_after_bundle_take(self.id(), result);
972        }
973        result
974    }
975}
976
977// SAFETY: We have exclusive world access so our pointers can't be invalidated externally
978pub(crate) struct BundleInserter<'w> {
979    world: UnsafeWorldCell<'w>,
980    bundle_info: ConstNonNull<BundleInfo>,
981    archetype_after_insert: ConstNonNull<ArchetypeAfterBundleInsert>,
982    table: NonNull<Table>,
983    archetype: NonNull<Archetype>,
984    archetype_move_type: ArchetypeMoveType,
985    change_tick: Tick,
986}
987
988/// The type of archetype move (or lack thereof) that will result from a bundle
989/// being inserted into an entity.
990pub(crate) enum ArchetypeMoveType {
991    /// If the entity already has all of the components that are being inserted,
992    /// its archetype won't change.
993    SameArchetype,
994    /// If only [`sparse set`](StorageType::SparseSet) components are being added,
995    /// the entity's archetype will change while keeping the same table.
996    NewArchetypeSameTable { new_archetype: NonNull<Archetype> },
997    /// If any [`table-stored`](StorageType::Table) components are being added,
998    /// both the entity's archetype and table will change.
999    NewArchetypeNewTable {
1000        new_archetype: NonNull<Archetype>,
1001        new_table: NonNull<Table>,
1002    },
1003}
1004
1005impl<'w> BundleInserter<'w> {
1006    #[inline]
1007    pub(crate) fn new<T: Bundle>(
1008        world: &'w mut World,
1009        archetype_id: ArchetypeId,
1010        change_tick: Tick,
1011    ) -> Self {
1012        // SAFETY: These come from the same world. `world.components_registrator` can't be used since we borrow other fields too.
1013        let mut registrator =
1014            unsafe { ComponentsRegistrator::new(&mut world.components, &mut world.component_ids) };
1015        let bundle_id = world
1016            .bundles
1017            .register_info::<T>(&mut registrator, &mut world.storages);
1018        // SAFETY: We just ensured this bundle exists
1019        unsafe { Self::new_with_id(world, archetype_id, bundle_id, change_tick) }
1020    }
1021
1022    /// Creates a new [`BundleInserter`].
1023    ///
1024    /// # Safety
1025    /// - Caller must ensure that `bundle_id` exists in `world.bundles`.
1026    #[inline]
1027    pub(crate) unsafe fn new_with_id(
1028        world: &'w mut World,
1029        archetype_id: ArchetypeId,
1030        bundle_id: BundleId,
1031        change_tick: Tick,
1032    ) -> Self {
1033        // SAFETY: We will not make any accesses to the command queue, component or resource data of this world
1034        let bundle_info = world.bundles.get_unchecked(bundle_id);
1035        let bundle_id = bundle_info.id();
1036        let new_archetype_id = bundle_info.insert_bundle_into_archetype(
1037            &mut world.archetypes,
1038            &mut world.storages,
1039            &world.components,
1040            &world.observers,
1041            archetype_id,
1042        );
1043        if new_archetype_id == archetype_id {
1044            let archetype = &mut world.archetypes[archetype_id];
1045            // SAFETY: The edge is assured to be initialized when we called insert_bundle_into_archetype
1046            let archetype_after_insert = unsafe {
1047                archetype
1048                    .edges()
1049                    .get_archetype_after_bundle_insert_internal(bundle_id)
1050                    .debug_checked_unwrap()
1051            };
1052            let table_id = archetype.table_id();
1053            let table = &mut world.storages.tables[table_id];
1054            Self {
1055                archetype_after_insert: archetype_after_insert.into(),
1056                archetype: archetype.into(),
1057                bundle_info: bundle_info.into(),
1058                table: table.into(),
1059                archetype_move_type: ArchetypeMoveType::SameArchetype,
1060                change_tick,
1061                world: world.as_unsafe_world_cell(),
1062            }
1063        } else {
1064            let (archetype, new_archetype) =
1065                world.archetypes.get_2_mut(archetype_id, new_archetype_id);
1066            // SAFETY: The edge is assured to be initialized when we called insert_bundle_into_archetype
1067            let archetype_after_insert = unsafe {
1068                archetype
1069                    .edges()
1070                    .get_archetype_after_bundle_insert_internal(bundle_id)
1071                    .debug_checked_unwrap()
1072            };
1073            let table_id = archetype.table_id();
1074            let new_table_id = new_archetype.table_id();
1075            if table_id == new_table_id {
1076                let table = &mut world.storages.tables[table_id];
1077                Self {
1078                    archetype_after_insert: archetype_after_insert.into(),
1079                    archetype: archetype.into(),
1080                    bundle_info: bundle_info.into(),
1081                    table: table.into(),
1082                    archetype_move_type: ArchetypeMoveType::NewArchetypeSameTable {
1083                        new_archetype: new_archetype.into(),
1084                    },
1085                    change_tick,
1086                    world: world.as_unsafe_world_cell(),
1087                }
1088            } else {
1089                let (table, new_table) = world.storages.tables.get_2_mut(table_id, new_table_id);
1090                Self {
1091                    archetype_after_insert: archetype_after_insert.into(),
1092                    archetype: archetype.into(),
1093                    bundle_info: bundle_info.into(),
1094                    table: table.into(),
1095                    archetype_move_type: ArchetypeMoveType::NewArchetypeNewTable {
1096                        new_archetype: new_archetype.into(),
1097                        new_table: new_table.into(),
1098                    },
1099                    change_tick,
1100                    world: world.as_unsafe_world_cell(),
1101                }
1102            }
1103        }
1104    }
1105
1106    /// # Safety
1107    /// `entity` must currently exist in the source archetype for this inserter. `location`
1108    /// must be `entity`'s location in the archetype. `T` must match this [`BundleInfo`]'s type
1109    #[inline]
1110    pub(crate) unsafe fn insert<T: DynamicBundle>(
1111        &mut self,
1112        entity: Entity,
1113        location: EntityLocation,
1114        bundle: T,
1115        insert_mode: InsertMode,
1116        caller: MaybeLocation,
1117        relationship_hook_mode: RelationshipHookMode,
1118    ) -> (EntityLocation, T::Effect) {
1119        let bundle_info = self.bundle_info.as_ref();
1120        let archetype_after_insert = self.archetype_after_insert.as_ref();
1121        let archetype = self.archetype.as_ref();
1122
1123        // SAFETY: All components in the bundle are guaranteed to exist in the World
1124        // as they must be initialized before creating the BundleInfo.
1125        unsafe {
1126            // SAFETY: Mutable references do not alias and will be dropped after this block
1127            let mut deferred_world = self.world.into_deferred();
1128
1129            if insert_mode == InsertMode::Replace {
1130                if archetype.has_replace_observer() {
1131                    deferred_world.trigger_observers(
1132                        ON_REPLACE,
1133                        entity,
1134                        archetype_after_insert.iter_existing(),
1135                        caller,
1136                    );
1137                }
1138                deferred_world.trigger_on_replace(
1139                    archetype,
1140                    entity,
1141                    archetype_after_insert.iter_existing(),
1142                    caller,
1143                    relationship_hook_mode,
1144                );
1145            }
1146        }
1147
1148        let table = self.table.as_mut();
1149
1150        // SAFETY: Archetype gets borrowed when running the on_replace observers above,
1151        // so this reference can only be promoted from shared to &mut down here, after they have been ran
1152        let archetype = self.archetype.as_mut();
1153
1154        let (new_archetype, new_location, after_effect) = match &mut self.archetype_move_type {
1155            ArchetypeMoveType::SameArchetype => {
1156                // SAFETY: Mutable references do not alias and will be dropped after this block
1157                let sparse_sets = {
1158                    let world = self.world.world_mut();
1159                    &mut world.storages.sparse_sets
1160                };
1161
1162                let after_effect = bundle_info.write_components(
1163                    table,
1164                    sparse_sets,
1165                    archetype_after_insert,
1166                    archetype_after_insert.required_components.iter(),
1167                    entity,
1168                    location.table_row,
1169                    self.change_tick,
1170                    bundle,
1171                    insert_mode,
1172                    caller,
1173                );
1174
1175                (archetype, location, after_effect)
1176            }
1177            ArchetypeMoveType::NewArchetypeSameTable { new_archetype } => {
1178                let new_archetype = new_archetype.as_mut();
1179
1180                // SAFETY: Mutable references do not alias and will be dropped after this block
1181                let (sparse_sets, entities) = {
1182                    let world = self.world.world_mut();
1183                    (&mut world.storages.sparse_sets, &mut world.entities)
1184                };
1185
1186                let result = archetype.swap_remove(location.archetype_row);
1187                if let Some(swapped_entity) = result.swapped_entity {
1188                    let swapped_location =
1189                        // SAFETY: If the swap was successful, swapped_entity must be valid.
1190                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1191                    entities.set(
1192                        swapped_entity.index(),
1193                        EntityLocation {
1194                            archetype_id: swapped_location.archetype_id,
1195                            archetype_row: location.archetype_row,
1196                            table_id: swapped_location.table_id,
1197                            table_row: swapped_location.table_row,
1198                        },
1199                    );
1200                }
1201                let new_location = new_archetype.allocate(entity, result.table_row);
1202                entities.set(entity.index(), new_location);
1203                let after_effect = bundle_info.write_components(
1204                    table,
1205                    sparse_sets,
1206                    archetype_after_insert,
1207                    archetype_after_insert.required_components.iter(),
1208                    entity,
1209                    result.table_row,
1210                    self.change_tick,
1211                    bundle,
1212                    insert_mode,
1213                    caller,
1214                );
1215
1216                (new_archetype, new_location, after_effect)
1217            }
1218            ArchetypeMoveType::NewArchetypeNewTable {
1219                new_archetype,
1220                new_table,
1221            } => {
1222                let new_table = new_table.as_mut();
1223                let new_archetype = new_archetype.as_mut();
1224
1225                // SAFETY: Mutable references do not alias and will be dropped after this block
1226                let (archetypes_ptr, sparse_sets, entities) = {
1227                    let world = self.world.world_mut();
1228                    let archetype_ptr: *mut Archetype = world.archetypes.archetypes.as_mut_ptr();
1229                    (
1230                        archetype_ptr,
1231                        &mut world.storages.sparse_sets,
1232                        &mut world.entities,
1233                    )
1234                };
1235                let result = archetype.swap_remove(location.archetype_row);
1236                if let Some(swapped_entity) = result.swapped_entity {
1237                    let swapped_location =
1238                        // SAFETY: If the swap was successful, swapped_entity must be valid.
1239                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1240                    entities.set(
1241                        swapped_entity.index(),
1242                        EntityLocation {
1243                            archetype_id: swapped_location.archetype_id,
1244                            archetype_row: location.archetype_row,
1245                            table_id: swapped_location.table_id,
1246                            table_row: swapped_location.table_row,
1247                        },
1248                    );
1249                }
1250                // PERF: store "non bundle" components in edge, then just move those to avoid
1251                // redundant copies
1252                let move_result = table.move_to_superset_unchecked(result.table_row, new_table);
1253                let new_location = new_archetype.allocate(entity, move_result.new_row);
1254                entities.set(entity.index(), new_location);
1255
1256                // If an entity was moved into this entity's table spot, update its table row.
1257                if let Some(swapped_entity) = move_result.swapped_entity {
1258                    let swapped_location =
1259                        // SAFETY: If the swap was successful, swapped_entity must be valid.
1260                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1261
1262                    entities.set(
1263                        swapped_entity.index(),
1264                        EntityLocation {
1265                            archetype_id: swapped_location.archetype_id,
1266                            archetype_row: swapped_location.archetype_row,
1267                            table_id: swapped_location.table_id,
1268                            table_row: result.table_row,
1269                        },
1270                    );
1271
1272                    if archetype.id() == swapped_location.archetype_id {
1273                        archetype
1274                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1275                    } else if new_archetype.id() == swapped_location.archetype_id {
1276                        new_archetype
1277                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1278                    } else {
1279                        // SAFETY: the only two borrowed archetypes are above and we just did collision checks
1280                        (*archetypes_ptr.add(swapped_location.archetype_id.index()))
1281                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1282                    }
1283                }
1284
1285                let after_effect = bundle_info.write_components(
1286                    new_table,
1287                    sparse_sets,
1288                    archetype_after_insert,
1289                    archetype_after_insert.required_components.iter(),
1290                    entity,
1291                    move_result.new_row,
1292                    self.change_tick,
1293                    bundle,
1294                    insert_mode,
1295                    caller,
1296                );
1297
1298                (new_archetype, new_location, after_effect)
1299            }
1300        };
1301
1302        let new_archetype = &*new_archetype;
1303        // SAFETY: We have no outstanding mutable references to world as they were dropped
1304        let mut deferred_world = unsafe { self.world.into_deferred() };
1305
1306        // SAFETY: All components in the bundle are guaranteed to exist in the World
1307        // as they must be initialized before creating the BundleInfo.
1308        unsafe {
1309            deferred_world.trigger_on_add(
1310                new_archetype,
1311                entity,
1312                archetype_after_insert.iter_added(),
1313                caller,
1314            );
1315            if new_archetype.has_add_observer() {
1316                deferred_world.trigger_observers(
1317                    ON_ADD,
1318                    entity,
1319                    archetype_after_insert.iter_added(),
1320                    caller,
1321                );
1322            }
1323            match insert_mode {
1324                InsertMode::Replace => {
1325                    // Insert triggers for both new and existing components if we're replacing them.
1326                    deferred_world.trigger_on_insert(
1327                        new_archetype,
1328                        entity,
1329                        archetype_after_insert.iter_inserted(),
1330                        caller,
1331                        relationship_hook_mode,
1332                    );
1333                    if new_archetype.has_insert_observer() {
1334                        deferred_world.trigger_observers(
1335                            ON_INSERT,
1336                            entity,
1337                            archetype_after_insert.iter_inserted(),
1338                            caller,
1339                        );
1340                    }
1341                }
1342                InsertMode::Keep => {
1343                    // Insert triggers only for new components if we're not replacing them (since
1344                    // nothing is actually inserted).
1345                    deferred_world.trigger_on_insert(
1346                        new_archetype,
1347                        entity,
1348                        archetype_after_insert.iter_added(),
1349                        caller,
1350                        relationship_hook_mode,
1351                    );
1352                    if new_archetype.has_insert_observer() {
1353                        deferred_world.trigger_observers(
1354                            ON_INSERT,
1355                            entity,
1356                            archetype_after_insert.iter_added(),
1357                            caller,
1358                        );
1359                    }
1360                }
1361            }
1362        }
1363
1364        (new_location, after_effect)
1365    }
1366
1367    #[inline]
1368    pub(crate) fn entities(&mut self) -> &mut Entities {
1369        // SAFETY: No outstanding references to self.world, changes to entities cannot invalidate our internal pointers
1370        unsafe { &mut self.world.world_mut().entities }
1371    }
1372}
1373
1374// SAFETY: We have exclusive world access so our pointers can't be invalidated externally
1375pub(crate) struct BundleSpawner<'w> {
1376    world: UnsafeWorldCell<'w>,
1377    bundle_info: ConstNonNull<BundleInfo>,
1378    table: NonNull<Table>,
1379    archetype: NonNull<Archetype>,
1380    change_tick: Tick,
1381}
1382
1383impl<'w> BundleSpawner<'w> {
1384    #[inline]
1385    pub fn new<T: Bundle>(world: &'w mut World, change_tick: Tick) -> Self {
1386        // SAFETY: These come from the same world. `world.components_registrator` can't be used since we borrow other fields too.
1387        let mut registrator =
1388            unsafe { ComponentsRegistrator::new(&mut world.components, &mut world.component_ids) };
1389        let bundle_id = world
1390            .bundles
1391            .register_info::<T>(&mut registrator, &mut world.storages);
1392        // SAFETY: we initialized this bundle_id in `init_info`
1393        unsafe { Self::new_with_id(world, bundle_id, change_tick) }
1394    }
1395
1396    /// Creates a new [`BundleSpawner`].
1397    ///
1398    /// # Safety
1399    /// Caller must ensure that `bundle_id` exists in `world.bundles`
1400    #[inline]
1401    pub(crate) unsafe fn new_with_id(
1402        world: &'w mut World,
1403        bundle_id: BundleId,
1404        change_tick: Tick,
1405    ) -> Self {
1406        let bundle_info = world.bundles.get_unchecked(bundle_id);
1407        let new_archetype_id = bundle_info.insert_bundle_into_archetype(
1408            &mut world.archetypes,
1409            &mut world.storages,
1410            &world.components,
1411            &world.observers,
1412            ArchetypeId::EMPTY,
1413        );
1414        let archetype = &mut world.archetypes[new_archetype_id];
1415        let table = &mut world.storages.tables[archetype.table_id()];
1416        Self {
1417            bundle_info: bundle_info.into(),
1418            table: table.into(),
1419            archetype: archetype.into(),
1420            change_tick,
1421            world: world.as_unsafe_world_cell(),
1422        }
1423    }
1424
1425    #[inline]
1426    pub fn reserve_storage(&mut self, additional: usize) {
1427        // SAFETY: There are no outstanding world references
1428        let (archetype, table) = unsafe { (self.archetype.as_mut(), self.table.as_mut()) };
1429        archetype.reserve(additional);
1430        table.reserve(additional);
1431    }
1432
1433    /// # Safety
1434    /// `entity` must be allocated (but non-existent), `T` must match this [`BundleInfo`]'s type
1435    #[inline]
1436    #[track_caller]
1437    pub unsafe fn spawn_non_existent<T: DynamicBundle>(
1438        &mut self,
1439        entity: Entity,
1440        bundle: T,
1441        caller: MaybeLocation,
1442    ) -> (EntityLocation, T::Effect) {
1443        // SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid
1444        let bundle_info = self.bundle_info.as_ref();
1445        let (location, after_effect) = {
1446            let table = self.table.as_mut();
1447            let archetype = self.archetype.as_mut();
1448
1449            // SAFETY: Mutable references do not alias and will be dropped after this block
1450            let (sparse_sets, entities) = {
1451                let world = self.world.world_mut();
1452                (&mut world.storages.sparse_sets, &mut world.entities)
1453            };
1454            let table_row = table.allocate(entity);
1455            let location = archetype.allocate(entity, table_row);
1456            let after_effect = bundle_info.write_components(
1457                table,
1458                sparse_sets,
1459                &SpawnBundleStatus,
1460                bundle_info.required_components.iter(),
1461                entity,
1462                table_row,
1463                self.change_tick,
1464                bundle,
1465                InsertMode::Replace,
1466                caller,
1467            );
1468            entities.set(entity.index(), location);
1469            (location, after_effect)
1470        };
1471
1472        // SAFETY: We have no outstanding mutable references to world as they were dropped
1473        let mut deferred_world = unsafe { self.world.into_deferred() };
1474        // SAFETY: `DeferredWorld` cannot provide mutable access to `Archetypes`.
1475        let archetype = self.archetype.as_ref();
1476        // SAFETY: All components in the bundle are guaranteed to exist in the World
1477        // as they must be initialized before creating the BundleInfo.
1478        unsafe {
1479            deferred_world.trigger_on_add(
1480                archetype,
1481                entity,
1482                bundle_info.iter_contributed_components(),
1483                caller,
1484            );
1485            if archetype.has_add_observer() {
1486                deferred_world.trigger_observers(
1487                    ON_ADD,
1488                    entity,
1489                    bundle_info.iter_contributed_components(),
1490                    caller,
1491                );
1492            }
1493            deferred_world.trigger_on_insert(
1494                archetype,
1495                entity,
1496                bundle_info.iter_contributed_components(),
1497                caller,
1498                RelationshipHookMode::Run,
1499            );
1500            if archetype.has_insert_observer() {
1501                deferred_world.trigger_observers(
1502                    ON_INSERT,
1503                    entity,
1504                    bundle_info.iter_contributed_components(),
1505                    caller,
1506                );
1507            }
1508        };
1509
1510        (location, after_effect)
1511    }
1512
1513    /// # Safety
1514    /// `T` must match this [`BundleInfo`]'s type
1515    #[inline]
1516    pub unsafe fn spawn<T: Bundle>(
1517        &mut self,
1518        bundle: T,
1519        caller: MaybeLocation,
1520    ) -> (Entity, T::Effect) {
1521        let entity = self.entities().alloc();
1522        // SAFETY: entity is allocated (but non-existent), `T` matches this BundleInfo's type
1523        let (_, after_effect) = unsafe { self.spawn_non_existent(entity, bundle, caller) };
1524        (entity, after_effect)
1525    }
1526
1527    #[inline]
1528    pub(crate) fn entities(&mut self) -> &mut Entities {
1529        // SAFETY: No outstanding references to self.world, changes to entities cannot invalidate our internal pointers
1530        unsafe { &mut self.world.world_mut().entities }
1531    }
1532
1533    /// # Safety
1534    /// - `Self` must be dropped after running this function as it may invalidate internal pointers.
1535    #[inline]
1536    pub(crate) unsafe fn flush_commands(&mut self) {
1537        // SAFETY: pointers on self can be invalidated,
1538        self.world.world_mut().flush();
1539    }
1540}
1541
1542/// Metadata for bundles. Stores a [`BundleInfo`] for each type of [`Bundle`] in a given world.
1543#[derive(Default)]
1544pub struct Bundles {
1545    bundle_infos: Vec<BundleInfo>,
1546    /// Cache static [`BundleId`]
1547    bundle_ids: TypeIdMap<BundleId>,
1548    /// Cache bundles, which contains both explicit and required components of [`Bundle`]
1549    contributed_bundle_ids: TypeIdMap<BundleId>,
1550    /// Cache dynamic [`BundleId`] with multiple components
1551    dynamic_bundle_ids: HashMap<Box<[ComponentId]>, BundleId>,
1552    dynamic_bundle_storages: HashMap<BundleId, Vec<StorageType>>,
1553    /// Cache optimized dynamic [`BundleId`] with single component
1554    dynamic_component_bundle_ids: HashMap<ComponentId, BundleId>,
1555    dynamic_component_storages: HashMap<BundleId, StorageType>,
1556}
1557
1558impl Bundles {
1559    /// The total number of [`Bundle`] registered in [`Storages`].
1560    pub fn len(&self) -> usize {
1561        self.bundle_infos.len()
1562    }
1563
1564    /// Returns true if no [`Bundle`] registered in [`Storages`].
1565    pub fn is_empty(&self) -> bool {
1566        self.len() == 0
1567    }
1568
1569    /// Iterate over [`BundleInfo`].
1570    pub fn iter(&self) -> impl Iterator<Item = &BundleInfo> {
1571        self.bundle_infos.iter()
1572    }
1573
1574    /// Gets the metadata associated with a specific type of bundle.
1575    /// Returns `None` if the bundle is not registered with the world.
1576    #[inline]
1577    pub fn get(&self, bundle_id: BundleId) -> Option<&BundleInfo> {
1578        self.bundle_infos.get(bundle_id.index())
1579    }
1580
1581    /// Gets the value identifying a specific type of bundle.
1582    /// Returns `None` if the bundle does not exist in the world,
1583    /// or if `type_id` does not correspond to a type of bundle.
1584    #[inline]
1585    pub fn get_id(&self, type_id: TypeId) -> Option<BundleId> {
1586        self.bundle_ids.get(&type_id).cloned()
1587    }
1588
1589    /// Registers a new [`BundleInfo`] for a statically known type.
1590    ///
1591    /// Also registers all the components in the bundle.
1592    pub(crate) fn register_info<T: Bundle>(
1593        &mut self,
1594        components: &mut ComponentsRegistrator,
1595        storages: &mut Storages,
1596    ) -> BundleId {
1597        let bundle_infos = &mut self.bundle_infos;
1598        *self.bundle_ids.entry(TypeId::of::<T>()).or_insert_with(|| {
1599            let mut component_ids= Vec::new();
1600            T::component_ids(components, &mut |id| component_ids.push(id));
1601            let id = BundleId(bundle_infos.len());
1602            let bundle_info =
1603                // SAFETY: T::component_id ensures:
1604                // - its info was created
1605                // - appropriate storage for it has been initialized.
1606                // - it was created in the same order as the components in T
1607                unsafe { BundleInfo::new(core::any::type_name::<T>(), storages, components, component_ids, id) };
1608            bundle_infos.push(bundle_info);
1609            id
1610        })
1611    }
1612
1613    /// Registers a new [`BundleInfo`], which contains both explicit and required components for a statically known type.
1614    ///
1615    /// Also registers all the components in the bundle.
1616    pub(crate) fn register_contributed_bundle_info<T: Bundle>(
1617        &mut self,
1618        components: &mut ComponentsRegistrator,
1619        storages: &mut Storages,
1620    ) -> BundleId {
1621        if let Some(id) = self.contributed_bundle_ids.get(&TypeId::of::<T>()).cloned() {
1622            id
1623        } else {
1624            let explicit_bundle_id = self.register_info::<T>(components, storages);
1625            // SAFETY: reading from `explicit_bundle_id` and creating new bundle in same time. Its valid because bundle hashmap allow this
1626            let id = unsafe {
1627                let (ptr, len) = {
1628                    // SAFETY: `explicit_bundle_id` is valid and defined above
1629                    let contributed = self
1630                        .get_unchecked(explicit_bundle_id)
1631                        .contributed_components();
1632                    (contributed.as_ptr(), contributed.len())
1633                };
1634                // SAFETY: this is sound because the contributed_components Vec for explicit_bundle_id will not be accessed mutably as
1635                // part of init_dynamic_info. No mutable references will be created and the allocation will remain valid.
1636                self.init_dynamic_info(storages, components, core::slice::from_raw_parts(ptr, len))
1637            };
1638            self.contributed_bundle_ids.insert(TypeId::of::<T>(), id);
1639            id
1640        }
1641    }
1642
1643    /// # Safety
1644    /// A [`BundleInfo`] with the given [`BundleId`] must have been initialized for this instance of `Bundles`.
1645    pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo {
1646        self.bundle_infos.get_unchecked(id.0)
1647    }
1648
1649    /// # Safety
1650    /// This [`BundleId`] must have been initialized with a single [`Component`] (via [`init_component_info`](Self::init_dynamic_info))
1651    pub(crate) unsafe fn get_storage_unchecked(&self, id: BundleId) -> StorageType {
1652        *self
1653            .dynamic_component_storages
1654            .get(&id)
1655            .debug_checked_unwrap()
1656    }
1657
1658    /// # Safety
1659    /// This [`BundleId`] must have been initialized with multiple [`Component`]s (via [`init_dynamic_info`](Self::init_dynamic_info))
1660    pub(crate) unsafe fn get_storages_unchecked(&mut self, id: BundleId) -> &mut Vec<StorageType> {
1661        self.dynamic_bundle_storages
1662            .get_mut(&id)
1663            .debug_checked_unwrap()
1664    }
1665
1666    /// Initializes a new [`BundleInfo`] for a dynamic [`Bundle`].
1667    ///
1668    /// # Panics
1669    ///
1670    /// Panics if any of the provided [`ComponentId`]s do not exist in the
1671    /// provided [`Components`].
1672    pub(crate) fn init_dynamic_info(
1673        &mut self,
1674        storages: &mut Storages,
1675        components: &Components,
1676        component_ids: &[ComponentId],
1677    ) -> BundleId {
1678        let bundle_infos = &mut self.bundle_infos;
1679
1680        // Use `raw_entry_mut` to avoid cloning `component_ids` to access `Entry`
1681        let (_, bundle_id) = self
1682            .dynamic_bundle_ids
1683            .raw_entry_mut()
1684            .from_key(component_ids)
1685            .or_insert_with(|| {
1686                let (id, storages) = initialize_dynamic_bundle(
1687                    bundle_infos,
1688                    storages,
1689                    components,
1690                    Vec::from(component_ids),
1691                );
1692                // SAFETY: The ID always increases when new bundles are added, and so, the ID is unique.
1693                unsafe {
1694                    self.dynamic_bundle_storages
1695                        .insert_unique_unchecked(id, storages);
1696                }
1697                (component_ids.into(), id)
1698            });
1699        *bundle_id
1700    }
1701
1702    /// Initializes a new [`BundleInfo`] for a dynamic [`Bundle`] with single component.
1703    ///
1704    /// # Panics
1705    ///
1706    /// Panics if the provided [`ComponentId`] does not exist in the provided [`Components`].
1707    pub(crate) fn init_component_info(
1708        &mut self,
1709        storages: &mut Storages,
1710        components: &Components,
1711        component_id: ComponentId,
1712    ) -> BundleId {
1713        let bundle_infos = &mut self.bundle_infos;
1714        let bundle_id = self
1715            .dynamic_component_bundle_ids
1716            .entry(component_id)
1717            .or_insert_with(|| {
1718                let (id, storage_type) = initialize_dynamic_bundle(
1719                    bundle_infos,
1720                    storages,
1721                    components,
1722                    vec![component_id],
1723                );
1724                self.dynamic_component_storages.insert(id, storage_type[0]);
1725                id
1726            });
1727        *bundle_id
1728    }
1729}
1730
1731/// Asserts that all components are part of [`Components`]
1732/// and initializes a [`BundleInfo`].
1733fn initialize_dynamic_bundle(
1734    bundle_infos: &mut Vec<BundleInfo>,
1735    storages: &mut Storages,
1736    components: &Components,
1737    component_ids: Vec<ComponentId>,
1738) -> (BundleId, Vec<StorageType>) {
1739    // Assert component existence
1740    let storage_types = component_ids.iter().map(|&id| {
1741        components.get_info(id).unwrap_or_else(|| {
1742            panic!(
1743                "init_dynamic_info called with component id {id:?} which doesn't exist in this world"
1744            )
1745        }).storage_type()
1746    }).collect();
1747
1748    let id = BundleId(bundle_infos.len());
1749    let bundle_info =
1750        // SAFETY: `component_ids` are valid as they were just checked
1751        unsafe { BundleInfo::new("<dynamic bundle>", storages, components, component_ids, id) };
1752    bundle_infos.push(bundle_info);
1753
1754    (id, storage_types)
1755}
1756
1757fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
1758    let mut remove_index = 0;
1759    source.retain(|value| {
1760        while remove_index < remove.len() && *value > remove[remove_index] {
1761            remove_index += 1;
1762        }
1763
1764        if remove_index < remove.len() {
1765            *value != remove[remove_index]
1766        } else {
1767            true
1768        }
1769    });
1770}
1771
1772#[cfg(test)]
1773mod tests {
1774    use crate::{component::HookContext, prelude::*, world::DeferredWorld};
1775    use alloc::vec;
1776
1777    #[derive(Component)]
1778    struct A;
1779
1780    #[derive(Component)]
1781    #[component(on_add = a_on_add, on_insert = a_on_insert, on_replace = a_on_replace, on_remove = a_on_remove)]
1782    struct AMacroHooks;
1783
1784    fn a_on_add(mut world: DeferredWorld, _: HookContext) {
1785        world.resource_mut::<R>().assert_order(0);
1786    }
1787
1788    fn a_on_insert(mut world: DeferredWorld, _: HookContext) {
1789        world.resource_mut::<R>().assert_order(1);
1790    }
1791
1792    fn a_on_replace(mut world: DeferredWorld, _: HookContext) {
1793        world.resource_mut::<R>().assert_order(2);
1794    }
1795
1796    fn a_on_remove(mut world: DeferredWorld, _: HookContext) {
1797        world.resource_mut::<R>().assert_order(3);
1798    }
1799
1800    #[derive(Component)]
1801    struct B;
1802
1803    #[derive(Component)]
1804    struct C;
1805
1806    #[derive(Component)]
1807    struct D;
1808
1809    #[derive(Component, Eq, PartialEq, Debug)]
1810    struct V(&'static str); // component with a value
1811
1812    #[derive(Resource, Default)]
1813    struct R(usize);
1814
1815    impl R {
1816        #[track_caller]
1817        fn assert_order(&mut self, count: usize) {
1818            assert_eq!(count, self.0);
1819            self.0 += 1;
1820        }
1821    }
1822
1823    #[test]
1824    fn component_hook_order_spawn_despawn() {
1825        let mut world = World::new();
1826        world.init_resource::<R>();
1827        world
1828            .register_component_hooks::<A>()
1829            .on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
1830            .on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
1831            .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
1832            .on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
1833
1834        let entity = world.spawn(A).id();
1835        world.despawn(entity);
1836        assert_eq!(4, world.resource::<R>().0);
1837    }
1838
1839    #[test]
1840    fn component_hook_order_spawn_despawn_with_macro_hooks() {
1841        let mut world = World::new();
1842        world.init_resource::<R>();
1843
1844        let entity = world.spawn(AMacroHooks).id();
1845        world.despawn(entity);
1846
1847        assert_eq!(4, world.resource::<R>().0);
1848    }
1849
1850    #[test]
1851    fn component_hook_order_insert_remove() {
1852        let mut world = World::new();
1853        world.init_resource::<R>();
1854        world
1855            .register_component_hooks::<A>()
1856            .on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
1857            .on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
1858            .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
1859            .on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
1860
1861        let mut entity = world.spawn_empty();
1862        entity.insert(A);
1863        entity.remove::<A>();
1864        entity.flush();
1865        assert_eq!(4, world.resource::<R>().0);
1866    }
1867
1868    #[test]
1869    fn component_hook_order_replace() {
1870        let mut world = World::new();
1871        world
1872            .register_component_hooks::<A>()
1873            .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(0))
1874            .on_insert(|mut world, _| {
1875                if let Some(mut r) = world.get_resource_mut::<R>() {
1876                    r.assert_order(1);
1877                }
1878            });
1879
1880        let entity = world.spawn(A).id();
1881        world.init_resource::<R>();
1882        let mut entity = world.entity_mut(entity);
1883        entity.insert(A);
1884        entity.insert_if_new(A); // this will not trigger on_replace or on_insert
1885        entity.flush();
1886        assert_eq!(2, world.resource::<R>().0);
1887    }
1888
1889    #[test]
1890    fn component_hook_order_recursive() {
1891        let mut world = World::new();
1892        world.init_resource::<R>();
1893        world
1894            .register_component_hooks::<A>()
1895            .on_add(|mut world, context| {
1896                world.resource_mut::<R>().assert_order(0);
1897                world.commands().entity(context.entity).insert(B);
1898            })
1899            .on_remove(|mut world, context| {
1900                world.resource_mut::<R>().assert_order(2);
1901                world.commands().entity(context.entity).remove::<B>();
1902            });
1903
1904        world
1905            .register_component_hooks::<B>()
1906            .on_add(|mut world, context| {
1907                world.resource_mut::<R>().assert_order(1);
1908                world.commands().entity(context.entity).remove::<A>();
1909            })
1910            .on_remove(|mut world, _| {
1911                world.resource_mut::<R>().assert_order(3);
1912            });
1913
1914        let entity = world.spawn(A).flush();
1915        let entity = world.get_entity(entity).unwrap();
1916        assert!(!entity.contains::<A>());
1917        assert!(!entity.contains::<B>());
1918        assert_eq!(4, world.resource::<R>().0);
1919    }
1920
1921    #[test]
1922    fn component_hook_order_recursive_multiple() {
1923        let mut world = World::new();
1924        world.init_resource::<R>();
1925        world
1926            .register_component_hooks::<A>()
1927            .on_add(|mut world, context| {
1928                world.resource_mut::<R>().assert_order(0);
1929                world.commands().entity(context.entity).insert(B).insert(C);
1930            });
1931
1932        world
1933            .register_component_hooks::<B>()
1934            .on_add(|mut world, context| {
1935                world.resource_mut::<R>().assert_order(1);
1936                world.commands().entity(context.entity).insert(D);
1937            });
1938
1939        world
1940            .register_component_hooks::<C>()
1941            .on_add(|mut world, _| {
1942                world.resource_mut::<R>().assert_order(3);
1943            });
1944
1945        world
1946            .register_component_hooks::<D>()
1947            .on_add(|mut world, _| {
1948                world.resource_mut::<R>().assert_order(2);
1949            });
1950
1951        world.spawn(A).flush();
1952        assert_eq!(4, world.resource::<R>().0);
1953    }
1954
1955    #[test]
1956    fn insert_if_new() {
1957        let mut world = World::new();
1958        let id = world.spawn(V("one")).id();
1959        let mut entity = world.entity_mut(id);
1960        entity.insert_if_new(V("two"));
1961        entity.insert_if_new((A, V("three")));
1962        entity.flush();
1963        // should still contain "one"
1964        let entity = world.entity(id);
1965        assert!(entity.contains::<A>());
1966        assert_eq!(entity.get(), Some(&V("one")));
1967    }
1968
1969    #[test]
1970    fn sorted_remove() {
1971        let mut a = vec![1, 2, 3, 4, 5, 6, 7];
1972        let b = vec![1, 2, 3, 5, 7];
1973        super::sorted_remove(&mut a, &b);
1974
1975        assert_eq!(a, vec![4, 6]);
1976
1977        let mut a = vec![1];
1978        let b = vec![1];
1979        super::sorted_remove(&mut a, &b);
1980
1981        assert_eq!(a, vec![]);
1982
1983        let mut a = vec![1];
1984        let b = vec![2];
1985        super::sorted_remove(&mut a, &b);
1986
1987        assert_eq!(a, vec![1]);
1988    }
1989}