1pub 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#[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    #[doc(hidden)]
154    fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId));
155
156    fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option<ComponentId>));
158
159    fn register_required_components(
161        _components: &mut ComponentsRegistrator,
162        _required_components: &mut RequiredComponents,
163    );
164}
165
166pub unsafe trait BundleFromComponents {
181    #[doc(hidden)]
188    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
189    where
190        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
192        Self: Sized;
193}
194
195pub trait DynamicBundle {
197    type Effect: BundleEffect;
199    #[doc(hidden)]
206    fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect;
207}
208
209pub trait BundleEffect {
218    fn apply(self, entity: &mut EntityWorldMut);
220}
221
222unsafe 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
249unsafe impl<C: Component> BundleFromComponents for C {
252    unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> Self
253    where
254        F: for<'a> FnMut(&'a mut T) -> OwningPtr<'a>,
256        Self: Sized,
257    {
258        let ptr = func(ctx);
259        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        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        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                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
381pub 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#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
416pub struct BundleId(usize);
417
418impl BundleId {
419    #[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#[derive(Clone, Copy, Eq, PartialEq)]
442pub enum InsertMode {
443    Replace,
445    Keep,
447}
448
449pub struct BundleInfo {
453    id: BundleId,
454    component_ids: Vec<ComponentId>,
463    required_components: Vec<RequiredComponentConstructor>,
464    explicit_components_len: usize,
465}
466
467impl BundleInfo {
468    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        let mut deduped = component_ids.clone();
483        deduped.sort_unstable();
484        deduped.dedup();
485        if deduped.len() != component_ids.len() {
486            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                    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        let explicit_components_len = component_ids.len();
509        let mut required_components = RequiredComponents::default();
510        for component_id in component_ids.iter().copied() {
511            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        let required_components = required_components
520            .0
521            .into_iter()
522            .map(|(component_id, v)| {
523                let info = unsafe { components.get_info_unchecked(component_id) };
525                storages.prepare_component(info);
526                component_ids.push(component_id);
529                v.constructor
530            })
531            .collect();
532
533        BundleInfo {
538            id,
539            component_ids,
540            required_components,
541            explicit_components_len,
542        }
543    }
544
545    #[inline]
547    pub const fn id(&self) -> BundleId {
548        self.id
549    }
550
551    #[inline]
555    pub fn explicit_components(&self) -> &[ComponentId] {
556        &self.component_ids[0..self.explicit_components_len]
557    }
558
559    #[inline]
562    pub fn required_components(&self) -> &[ComponentId] {
563        &self.component_ids[self.explicit_components_len..]
564    }
565
566    #[inline]
570    pub fn contributed_components(&self) -> &[ComponentId] {
571        &self.component_ids
572    }
573
574    #[inline]
577    pub fn iter_explicit_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
578        self.explicit_components().iter().copied()
579    }
580
581    #[inline]
585    pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
586        self.component_ids.iter().copied()
587    }
588
589    pub fn iter_required_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
592        self.required_components().iter().copied()
593    }
594
595    #[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        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            match storage_type {
634                StorageType::Table => {
635                    let status = unsafe { bundle_component_status.get_status(bundle_component) };
637                    let column = table.get_column_mut(component_id).debug_checked_unwrap();
640                    match (status, insert_mode) {
641                        (ComponentStatus::Added, _) => {
642                            column.initialize(table_row, component_ptr, change_tick, caller);
643                        }
644                        (ComponentStatus::Existing, InsertMode::Replace) => {
645                            column.replace(table_row, component_ptr, change_tick, caller);
646                        }
647                        (ComponentStatus::Existing, InsertMode::Keep) => {
648                            if let Some(drop_fn) = table.get_drop_for(component_id) {
649                                drop_fn(component_ptr);
650                            }
651                        }
652                    }
653                }
654                StorageType::SparseSet => {
655                    let sparse_set =
656                        unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
659                    sparse_set.insert(entity, component_ptr, change_tick, caller);
660                }
661            }
662            bundle_component += 1;
663        });
664
665        for required_component in required_components {
666            required_component.initialize(
667                table,
668                sparse_sets,
669                change_tick,
670                table_row,
671                entity,
672                caller,
673            );
674        }
675
676        after_effect
677    }
678
679    pub(crate) unsafe fn initialize_required_component(
692        table: &mut Table,
693        sparse_sets: &mut SparseSets,
694        change_tick: Tick,
695        table_row: TableRow,
696        entity: Entity,
697        component_id: ComponentId,
698        storage_type: StorageType,
699        component_ptr: OwningPtr,
700        caller: MaybeLocation,
701    ) {
702        {
703            match storage_type {
704                StorageType::Table => {
705                    let column =
706                        unsafe { table.get_column_mut(component_id).debug_checked_unwrap() };
709                    column.initialize(table_row, component_ptr, change_tick, caller);
710                }
711                StorageType::SparseSet => {
712                    let sparse_set =
713                        unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() };
716                    sparse_set.insert(entity, component_ptr, change_tick, caller);
717                }
718            }
719        }
720    }
721
722    pub(crate) unsafe fn insert_bundle_into_archetype(
731        &self,
732        archetypes: &mut Archetypes,
733        storages: &mut Storages,
734        components: &Components,
735        observers: &Observers,
736        archetype_id: ArchetypeId,
737    ) -> ArchetypeId {
738        if let Some(archetype_after_insert_id) = archetypes[archetype_id]
739            .edges()
740            .get_archetype_after_bundle_insert(self.id)
741        {
742            return archetype_after_insert_id;
743        }
744        let mut new_table_components = Vec::new();
745        let mut new_sparse_set_components = Vec::new();
746        let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
747        let mut added_required_components = Vec::new();
748        let mut added = Vec::new();
749        let mut existing = Vec::new();
750
751        let current_archetype = &mut archetypes[archetype_id];
752        for component_id in self.iter_explicit_components() {
753            if current_archetype.contains(component_id) {
754                bundle_status.push(ComponentStatus::Existing);
755                existing.push(component_id);
756            } else {
757                bundle_status.push(ComponentStatus::Added);
758                added.push(component_id);
759                let component_info = unsafe { components.get_info_unchecked(component_id) };
761                match component_info.storage_type() {
762                    StorageType::Table => new_table_components.push(component_id),
763                    StorageType::SparseSet => new_sparse_set_components.push(component_id),
764                }
765            }
766        }
767
768        for (index, component_id) in self.iter_required_components().enumerate() {
769            if !current_archetype.contains(component_id) {
770                added_required_components.push(self.required_components[index].clone());
771                added.push(component_id);
772                let component_info = unsafe { components.get_info_unchecked(component_id) };
774                match component_info.storage_type() {
775                    StorageType::Table => {
776                        new_table_components.push(component_id);
777                    }
778                    StorageType::SparseSet => {
779                        new_sparse_set_components.push(component_id);
780                    }
781                }
782            }
783        }
784
785        if new_table_components.is_empty() && new_sparse_set_components.is_empty() {
786            let edges = current_archetype.edges_mut();
787            edges.cache_archetype_after_bundle_insert(
789                self.id,
790                archetype_id,
791                bundle_status,
792                added_required_components,
793                added,
794                existing,
795            );
796            archetype_id
797        } else {
798            let table_id;
799            let table_components;
800            let sparse_set_components;
801            {
803                let current_archetype = &archetypes[archetype_id];
804                table_components = if new_table_components.is_empty() {
805                    table_id = current_archetype.table_id();
807                    current_archetype.table_components().collect()
808                } else {
809                    new_table_components.extend(current_archetype.table_components());
810                    new_table_components.sort_unstable();
812                    table_id = unsafe {
814                        storages
815                            .tables
816                            .get_id_or_insert(&new_table_components, components)
817                    };
818
819                    new_table_components
820                };
821
822                sparse_set_components = if new_sparse_set_components.is_empty() {
823                    current_archetype.sparse_set_components().collect()
824                } else {
825                    new_sparse_set_components.extend(current_archetype.sparse_set_components());
826                    new_sparse_set_components.sort_unstable();
828                    new_sparse_set_components
829                };
830            };
831            let new_archetype_id = archetypes.get_id_or_insert(
833                components,
834                observers,
835                table_id,
836                table_components,
837                sparse_set_components,
838            );
839            archetypes[archetype_id]
841                .edges_mut()
842                .cache_archetype_after_bundle_insert(
843                    self.id,
844                    new_archetype_id,
845                    bundle_status,
846                    added_required_components,
847                    added,
848                    existing,
849                );
850            new_archetype_id
851        }
852    }
853
854    pub(crate) unsafe fn remove_bundle_from_archetype(
870        &self,
871        archetypes: &mut Archetypes,
872        storages: &mut Storages,
873        components: &Components,
874        observers: &Observers,
875        archetype_id: ArchetypeId,
876        intersection: bool,
877    ) -> Option<ArchetypeId> {
878        let archetype_after_remove_result = {
881            let edges = archetypes[archetype_id].edges();
882            if intersection {
883                edges.get_archetype_after_bundle_remove(self.id())
884            } else {
885                edges.get_archetype_after_bundle_take(self.id())
886            }
887        };
888        let result = if let Some(result) = archetype_after_remove_result {
889            result
891        } else {
892            let mut next_table_components;
893            let mut next_sparse_set_components;
894            let next_table_id;
895            {
896                let current_archetype = &mut archetypes[archetype_id];
897                let mut removed_table_components = Vec::new();
898                let mut removed_sparse_set_components = Vec::new();
899                for component_id in self.iter_explicit_components() {
900                    if current_archetype.contains(component_id) {
901                        let component_info = unsafe { components.get_info_unchecked(component_id) };
903                        match component_info.storage_type() {
904                            StorageType::Table => removed_table_components.push(component_id),
905                            StorageType::SparseSet => {
906                                removed_sparse_set_components.push(component_id);
907                            }
908                        }
909                    } else if !intersection {
910                        current_archetype
913                            .edges_mut()
914                            .cache_archetype_after_bundle_take(self.id(), None);
915                        return None;
916                    }
917                }
918
919                removed_table_components.sort_unstable();
922                removed_sparse_set_components.sort_unstable();
923                next_table_components = current_archetype.table_components().collect();
924                next_sparse_set_components = current_archetype.sparse_set_components().collect();
925                sorted_remove(&mut next_table_components, &removed_table_components);
926                sorted_remove(
927                    &mut next_sparse_set_components,
928                    &removed_sparse_set_components,
929                );
930
931                next_table_id = if removed_table_components.is_empty() {
932                    current_archetype.table_id()
933                } else {
934                    unsafe {
936                        storages
937                            .tables
938                            .get_id_or_insert(&next_table_components, components)
939                    }
940                };
941            }
942
943            let new_archetype_id = archetypes.get_id_or_insert(
944                components,
945                observers,
946                next_table_id,
947                next_table_components,
948                next_sparse_set_components,
949            );
950            Some(new_archetype_id)
951        };
952        let current_archetype = &mut archetypes[archetype_id];
953        if intersection {
955            current_archetype
956                .edges_mut()
957                .cache_archetype_after_bundle_remove(self.id(), result);
958        } else {
959            current_archetype
960                .edges_mut()
961                .cache_archetype_after_bundle_take(self.id(), result);
962        }
963        result
964    }
965}
966
967pub(crate) struct BundleInserter<'w> {
969    world: UnsafeWorldCell<'w>,
970    bundle_info: ConstNonNull<BundleInfo>,
971    archetype_after_insert: ConstNonNull<ArchetypeAfterBundleInsert>,
972    table: NonNull<Table>,
973    archetype: NonNull<Archetype>,
974    archetype_move_type: ArchetypeMoveType,
975    change_tick: Tick,
976}
977
978pub(crate) enum ArchetypeMoveType {
981    SameArchetype,
984    NewArchetypeSameTable { new_archetype: NonNull<Archetype> },
987    NewArchetypeNewTable {
990        new_archetype: NonNull<Archetype>,
991        new_table: NonNull<Table>,
992    },
993}
994
995impl<'w> BundleInserter<'w> {
996    #[inline]
997    pub(crate) fn new<T: Bundle>(
998        world: &'w mut World,
999        archetype_id: ArchetypeId,
1000        change_tick: Tick,
1001    ) -> Self {
1002        let mut registrator =
1004            unsafe { ComponentsRegistrator::new(&mut world.components, &mut world.component_ids) };
1005        let bundle_id = world
1006            .bundles
1007            .register_info::<T>(&mut registrator, &mut world.storages);
1008        unsafe { Self::new_with_id(world, archetype_id, bundle_id, change_tick) }
1010    }
1011
1012    #[inline]
1017    pub(crate) unsafe fn new_with_id(
1018        world: &'w mut World,
1019        archetype_id: ArchetypeId,
1020        bundle_id: BundleId,
1021        change_tick: Tick,
1022    ) -> Self {
1023        let bundle_info = world.bundles.get_unchecked(bundle_id);
1025        let bundle_id = bundle_info.id();
1026        let new_archetype_id = bundle_info.insert_bundle_into_archetype(
1027            &mut world.archetypes,
1028            &mut world.storages,
1029            &world.components,
1030            &world.observers,
1031            archetype_id,
1032        );
1033        if new_archetype_id == archetype_id {
1034            let archetype = &mut world.archetypes[archetype_id];
1035            let archetype_after_insert = unsafe {
1037                archetype
1038                    .edges()
1039                    .get_archetype_after_bundle_insert_internal(bundle_id)
1040                    .debug_checked_unwrap()
1041            };
1042            let table_id = archetype.table_id();
1043            let table = &mut world.storages.tables[table_id];
1044            Self {
1045                archetype_after_insert: archetype_after_insert.into(),
1046                archetype: archetype.into(),
1047                bundle_info: bundle_info.into(),
1048                table: table.into(),
1049                archetype_move_type: ArchetypeMoveType::SameArchetype,
1050                change_tick,
1051                world: world.as_unsafe_world_cell(),
1052            }
1053        } else {
1054            let (archetype, new_archetype) =
1055                world.archetypes.get_2_mut(archetype_id, new_archetype_id);
1056            let archetype_after_insert = unsafe {
1058                archetype
1059                    .edges()
1060                    .get_archetype_after_bundle_insert_internal(bundle_id)
1061                    .debug_checked_unwrap()
1062            };
1063            let table_id = archetype.table_id();
1064            let new_table_id = new_archetype.table_id();
1065            if table_id == new_table_id {
1066                let table = &mut world.storages.tables[table_id];
1067                Self {
1068                    archetype_after_insert: archetype_after_insert.into(),
1069                    archetype: archetype.into(),
1070                    bundle_info: bundle_info.into(),
1071                    table: table.into(),
1072                    archetype_move_type: ArchetypeMoveType::NewArchetypeSameTable {
1073                        new_archetype: new_archetype.into(),
1074                    },
1075                    change_tick,
1076                    world: world.as_unsafe_world_cell(),
1077                }
1078            } else {
1079                let (table, new_table) = world.storages.tables.get_2_mut(table_id, new_table_id);
1080                Self {
1081                    archetype_after_insert: archetype_after_insert.into(),
1082                    archetype: archetype.into(),
1083                    bundle_info: bundle_info.into(),
1084                    table: table.into(),
1085                    archetype_move_type: ArchetypeMoveType::NewArchetypeNewTable {
1086                        new_archetype: new_archetype.into(),
1087                        new_table: new_table.into(),
1088                    },
1089                    change_tick,
1090                    world: world.as_unsafe_world_cell(),
1091                }
1092            }
1093        }
1094    }
1095
1096    #[inline]
1100    pub(crate) unsafe fn insert<T: DynamicBundle>(
1101        &mut self,
1102        entity: Entity,
1103        location: EntityLocation,
1104        bundle: T,
1105        insert_mode: InsertMode,
1106        caller: MaybeLocation,
1107        relationship_hook_mode: RelationshipHookMode,
1108    ) -> (EntityLocation, T::Effect) {
1109        let bundle_info = self.bundle_info.as_ref();
1110        let archetype_after_insert = self.archetype_after_insert.as_ref();
1111        let archetype = self.archetype.as_ref();
1112
1113        unsafe {
1116            let mut deferred_world = self.world.into_deferred();
1118
1119            if insert_mode == InsertMode::Replace {
1120                if archetype.has_replace_observer() {
1121                    deferred_world.trigger_observers(
1122                        ON_REPLACE,
1123                        entity,
1124                        archetype_after_insert.iter_existing(),
1125                        caller,
1126                    );
1127                }
1128                deferred_world.trigger_on_replace(
1129                    archetype,
1130                    entity,
1131                    archetype_after_insert.iter_existing(),
1132                    caller,
1133                    relationship_hook_mode,
1134                );
1135            }
1136        }
1137
1138        let table = self.table.as_mut();
1139
1140        let archetype = self.archetype.as_mut();
1143
1144        let (new_archetype, new_location, after_effect) = match &mut self.archetype_move_type {
1145            ArchetypeMoveType::SameArchetype => {
1146                let sparse_sets = {
1148                    let world = self.world.world_mut();
1149                    &mut world.storages.sparse_sets
1150                };
1151
1152                let after_effect = bundle_info.write_components(
1153                    table,
1154                    sparse_sets,
1155                    archetype_after_insert,
1156                    archetype_after_insert.required_components.iter(),
1157                    entity,
1158                    location.table_row,
1159                    self.change_tick,
1160                    bundle,
1161                    insert_mode,
1162                    caller,
1163                );
1164
1165                (archetype, location, after_effect)
1166            }
1167            ArchetypeMoveType::NewArchetypeSameTable { new_archetype } => {
1168                let new_archetype = new_archetype.as_mut();
1169
1170                let (sparse_sets, entities) = {
1172                    let world = self.world.world_mut();
1173                    (&mut world.storages.sparse_sets, &mut world.entities)
1174                };
1175
1176                let result = archetype.swap_remove(location.archetype_row);
1177                if let Some(swapped_entity) = result.swapped_entity {
1178                    let swapped_location =
1179                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1181                    entities.set(
1182                        swapped_entity.index(),
1183                        EntityLocation {
1184                            archetype_id: swapped_location.archetype_id,
1185                            archetype_row: location.archetype_row,
1186                            table_id: swapped_location.table_id,
1187                            table_row: swapped_location.table_row,
1188                        },
1189                    );
1190                }
1191                let new_location = new_archetype.allocate(entity, result.table_row);
1192                entities.set(entity.index(), new_location);
1193                let after_effect = bundle_info.write_components(
1194                    table,
1195                    sparse_sets,
1196                    archetype_after_insert,
1197                    archetype_after_insert.required_components.iter(),
1198                    entity,
1199                    result.table_row,
1200                    self.change_tick,
1201                    bundle,
1202                    insert_mode,
1203                    caller,
1204                );
1205
1206                (new_archetype, new_location, after_effect)
1207            }
1208            ArchetypeMoveType::NewArchetypeNewTable {
1209                new_archetype,
1210                new_table,
1211            } => {
1212                let new_table = new_table.as_mut();
1213                let new_archetype = new_archetype.as_mut();
1214
1215                let (archetypes_ptr, sparse_sets, entities) = {
1217                    let world = self.world.world_mut();
1218                    let archetype_ptr: *mut Archetype = world.archetypes.archetypes.as_mut_ptr();
1219                    (
1220                        archetype_ptr,
1221                        &mut world.storages.sparse_sets,
1222                        &mut world.entities,
1223                    )
1224                };
1225                let result = archetype.swap_remove(location.archetype_row);
1226                if let Some(swapped_entity) = result.swapped_entity {
1227                    let swapped_location =
1228                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1230                    entities.set(
1231                        swapped_entity.index(),
1232                        EntityLocation {
1233                            archetype_id: swapped_location.archetype_id,
1234                            archetype_row: location.archetype_row,
1235                            table_id: swapped_location.table_id,
1236                            table_row: swapped_location.table_row,
1237                        },
1238                    );
1239                }
1240                let move_result = table.move_to_superset_unchecked(result.table_row, new_table);
1243                let new_location = new_archetype.allocate(entity, move_result.new_row);
1244                entities.set(entity.index(), new_location);
1245
1246                if let Some(swapped_entity) = move_result.swapped_entity {
1248                    let swapped_location =
1249                        unsafe { entities.get(swapped_entity).debug_checked_unwrap() };
1251
1252                    entities.set(
1253                        swapped_entity.index(),
1254                        EntityLocation {
1255                            archetype_id: swapped_location.archetype_id,
1256                            archetype_row: swapped_location.archetype_row,
1257                            table_id: swapped_location.table_id,
1258                            table_row: result.table_row,
1259                        },
1260                    );
1261
1262                    if archetype.id() == swapped_location.archetype_id {
1263                        archetype
1264                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1265                    } else if new_archetype.id() == swapped_location.archetype_id {
1266                        new_archetype
1267                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1268                    } else {
1269                        (*archetypes_ptr.add(swapped_location.archetype_id.index()))
1271                            .set_entity_table_row(swapped_location.archetype_row, result.table_row);
1272                    }
1273                }
1274
1275                let after_effect = bundle_info.write_components(
1276                    new_table,
1277                    sparse_sets,
1278                    archetype_after_insert,
1279                    archetype_after_insert.required_components.iter(),
1280                    entity,
1281                    move_result.new_row,
1282                    self.change_tick,
1283                    bundle,
1284                    insert_mode,
1285                    caller,
1286                );
1287
1288                (new_archetype, new_location, after_effect)
1289            }
1290        };
1291
1292        let new_archetype = &*new_archetype;
1293        let mut deferred_world = unsafe { self.world.into_deferred() };
1295
1296        unsafe {
1299            deferred_world.trigger_on_add(
1300                new_archetype,
1301                entity,
1302                archetype_after_insert.iter_added(),
1303                caller,
1304            );
1305            if new_archetype.has_add_observer() {
1306                deferred_world.trigger_observers(
1307                    ON_ADD,
1308                    entity,
1309                    archetype_after_insert.iter_added(),
1310                    caller,
1311                );
1312            }
1313            match insert_mode {
1314                InsertMode::Replace => {
1315                    deferred_world.trigger_on_insert(
1317                        new_archetype,
1318                        entity,
1319                        archetype_after_insert.iter_inserted(),
1320                        caller,
1321                        relationship_hook_mode,
1322                    );
1323                    if new_archetype.has_insert_observer() {
1324                        deferred_world.trigger_observers(
1325                            ON_INSERT,
1326                            entity,
1327                            archetype_after_insert.iter_inserted(),
1328                            caller,
1329                        );
1330                    }
1331                }
1332                InsertMode::Keep => {
1333                    deferred_world.trigger_on_insert(
1336                        new_archetype,
1337                        entity,
1338                        archetype_after_insert.iter_added(),
1339                        caller,
1340                        relationship_hook_mode,
1341                    );
1342                    if new_archetype.has_insert_observer() {
1343                        deferred_world.trigger_observers(
1344                            ON_INSERT,
1345                            entity,
1346                            archetype_after_insert.iter_added(),
1347                            caller,
1348                        );
1349                    }
1350                }
1351            }
1352        }
1353
1354        (new_location, after_effect)
1355    }
1356
1357    #[inline]
1358    pub(crate) fn entities(&mut self) -> &mut Entities {
1359        unsafe { &mut self.world.world_mut().entities }
1361    }
1362}
1363
1364pub(crate) struct BundleSpawner<'w> {
1366    world: UnsafeWorldCell<'w>,
1367    bundle_info: ConstNonNull<BundleInfo>,
1368    table: NonNull<Table>,
1369    archetype: NonNull<Archetype>,
1370    change_tick: Tick,
1371}
1372
1373impl<'w> BundleSpawner<'w> {
1374    #[inline]
1375    pub fn new<T: Bundle>(world: &'w mut World, change_tick: Tick) -> Self {
1376        let mut registrator =
1378            unsafe { ComponentsRegistrator::new(&mut world.components, &mut world.component_ids) };
1379        let bundle_id = world
1380            .bundles
1381            .register_info::<T>(&mut registrator, &mut world.storages);
1382        unsafe { Self::new_with_id(world, bundle_id, change_tick) }
1384    }
1385
1386    #[inline]
1391    pub(crate) unsafe fn new_with_id(
1392        world: &'w mut World,
1393        bundle_id: BundleId,
1394        change_tick: Tick,
1395    ) -> Self {
1396        let bundle_info = world.bundles.get_unchecked(bundle_id);
1397        let new_archetype_id = bundle_info.insert_bundle_into_archetype(
1398            &mut world.archetypes,
1399            &mut world.storages,
1400            &world.components,
1401            &world.observers,
1402            ArchetypeId::EMPTY,
1403        );
1404        let archetype = &mut world.archetypes[new_archetype_id];
1405        let table = &mut world.storages.tables[archetype.table_id()];
1406        Self {
1407            bundle_info: bundle_info.into(),
1408            table: table.into(),
1409            archetype: archetype.into(),
1410            change_tick,
1411            world: world.as_unsafe_world_cell(),
1412        }
1413    }
1414
1415    #[inline]
1416    pub fn reserve_storage(&mut self, additional: usize) {
1417        let (archetype, table) = unsafe { (self.archetype.as_mut(), self.table.as_mut()) };
1419        archetype.reserve(additional);
1420        table.reserve(additional);
1421    }
1422
1423    #[inline]
1426    #[track_caller]
1427    pub unsafe fn spawn_non_existent<T: DynamicBundle>(
1428        &mut self,
1429        entity: Entity,
1430        bundle: T,
1431        caller: MaybeLocation,
1432    ) -> (EntityLocation, T::Effect) {
1433        let bundle_info = self.bundle_info.as_ref();
1435        let (location, after_effect) = {
1436            let table = self.table.as_mut();
1437            let archetype = self.archetype.as_mut();
1438
1439            let (sparse_sets, entities) = {
1441                let world = self.world.world_mut();
1442                (&mut world.storages.sparse_sets, &mut world.entities)
1443            };
1444            let table_row = table.allocate(entity);
1445            let location = archetype.allocate(entity, table_row);
1446            let after_effect = bundle_info.write_components(
1447                table,
1448                sparse_sets,
1449                &SpawnBundleStatus,
1450                bundle_info.required_components.iter(),
1451                entity,
1452                table_row,
1453                self.change_tick,
1454                bundle,
1455                InsertMode::Replace,
1456                caller,
1457            );
1458            entities.set(entity.index(), location);
1459            (location, after_effect)
1460        };
1461
1462        let mut deferred_world = unsafe { self.world.into_deferred() };
1464        let archetype = self.archetype.as_ref();
1466        unsafe {
1469            deferred_world.trigger_on_add(
1470                archetype,
1471                entity,
1472                bundle_info.iter_contributed_components(),
1473                caller,
1474            );
1475            if archetype.has_add_observer() {
1476                deferred_world.trigger_observers(
1477                    ON_ADD,
1478                    entity,
1479                    bundle_info.iter_contributed_components(),
1480                    caller,
1481                );
1482            }
1483            deferred_world.trigger_on_insert(
1484                archetype,
1485                entity,
1486                bundle_info.iter_contributed_components(),
1487                caller,
1488                RelationshipHookMode::Run,
1489            );
1490            if archetype.has_insert_observer() {
1491                deferred_world.trigger_observers(
1492                    ON_INSERT,
1493                    entity,
1494                    bundle_info.iter_contributed_components(),
1495                    caller,
1496                );
1497            }
1498        };
1499
1500        (location, after_effect)
1501    }
1502
1503    #[inline]
1506    pub unsafe fn spawn<T: Bundle>(
1507        &mut self,
1508        bundle: T,
1509        caller: MaybeLocation,
1510    ) -> (Entity, T::Effect) {
1511        let entity = self.entities().alloc();
1512        let (_, after_effect) = unsafe { self.spawn_non_existent(entity, bundle, caller) };
1514        (entity, after_effect)
1515    }
1516
1517    #[inline]
1518    pub(crate) fn entities(&mut self) -> &mut Entities {
1519        unsafe { &mut self.world.world_mut().entities }
1521    }
1522
1523    #[inline]
1526    pub(crate) unsafe fn flush_commands(&mut self) {
1527        self.world.world_mut().flush();
1529    }
1530}
1531
1532#[derive(Default)]
1534pub struct Bundles {
1535    bundle_infos: Vec<BundleInfo>,
1536    bundle_ids: TypeIdMap<BundleId>,
1538    contributed_bundle_ids: TypeIdMap<BundleId>,
1540    dynamic_bundle_ids: HashMap<Box<[ComponentId]>, BundleId>,
1542    dynamic_bundle_storages: HashMap<BundleId, Vec<StorageType>>,
1543    dynamic_component_bundle_ids: HashMap<ComponentId, BundleId>,
1545    dynamic_component_storages: HashMap<BundleId, StorageType>,
1546}
1547
1548impl Bundles {
1549    pub fn len(&self) -> usize {
1551        self.bundle_infos.len()
1552    }
1553
1554    pub fn is_empty(&self) -> bool {
1556        self.len() == 0
1557    }
1558
1559    pub fn iter(&self) -> impl Iterator<Item = &BundleInfo> {
1561        self.bundle_infos.iter()
1562    }
1563
1564    #[inline]
1567    pub fn get(&self, bundle_id: BundleId) -> Option<&BundleInfo> {
1568        self.bundle_infos.get(bundle_id.index())
1569    }
1570
1571    #[inline]
1575    pub fn get_id(&self, type_id: TypeId) -> Option<BundleId> {
1576        self.bundle_ids.get(&type_id).cloned()
1577    }
1578
1579    pub(crate) fn register_info<T: Bundle>(
1583        &mut self,
1584        components: &mut ComponentsRegistrator,
1585        storages: &mut Storages,
1586    ) -> BundleId {
1587        let bundle_infos = &mut self.bundle_infos;
1588        *self.bundle_ids.entry(TypeId::of::<T>()).or_insert_with(|| {
1589            let mut component_ids= Vec::new();
1590            T::component_ids(components, &mut |id| component_ids.push(id));
1591            let id = BundleId(bundle_infos.len());
1592            let bundle_info =
1593                unsafe { BundleInfo::new(core::any::type_name::<T>(), storages, components, component_ids, id) };
1598            bundle_infos.push(bundle_info);
1599            id
1600        })
1601    }
1602
1603    pub(crate) fn register_contributed_bundle_info<T: Bundle>(
1607        &mut self,
1608        components: &mut ComponentsRegistrator,
1609        storages: &mut Storages,
1610    ) -> BundleId {
1611        if let Some(id) = self.contributed_bundle_ids.get(&TypeId::of::<T>()).cloned() {
1612            id
1613        } else {
1614            let explicit_bundle_id = self.register_info::<T>(components, storages);
1615            let id = unsafe {
1617                let (ptr, len) = {
1618                    let contributed = self
1620                        .get_unchecked(explicit_bundle_id)
1621                        .contributed_components();
1622                    (contributed.as_ptr(), contributed.len())
1623                };
1624                self.init_dynamic_info(storages, components, core::slice::from_raw_parts(ptr, len))
1627            };
1628            self.contributed_bundle_ids.insert(TypeId::of::<T>(), id);
1629            id
1630        }
1631    }
1632
1633    pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo {
1636        self.bundle_infos.get_unchecked(id.0)
1637    }
1638
1639    pub(crate) unsafe fn get_storage_unchecked(&self, id: BundleId) -> StorageType {
1642        *self
1643            .dynamic_component_storages
1644            .get(&id)
1645            .debug_checked_unwrap()
1646    }
1647
1648    pub(crate) unsafe fn get_storages_unchecked(&mut self, id: BundleId) -> &mut Vec<StorageType> {
1651        self.dynamic_bundle_storages
1652            .get_mut(&id)
1653            .debug_checked_unwrap()
1654    }
1655
1656    pub(crate) fn init_dynamic_info(
1663        &mut self,
1664        storages: &mut Storages,
1665        components: &Components,
1666        component_ids: &[ComponentId],
1667    ) -> BundleId {
1668        let bundle_infos = &mut self.bundle_infos;
1669
1670        let (_, bundle_id) = self
1672            .dynamic_bundle_ids
1673            .raw_entry_mut()
1674            .from_key(component_ids)
1675            .or_insert_with(|| {
1676                let (id, storages) = initialize_dynamic_bundle(
1677                    bundle_infos,
1678                    storages,
1679                    components,
1680                    Vec::from(component_ids),
1681                );
1682                unsafe {
1684                    self.dynamic_bundle_storages
1685                        .insert_unique_unchecked(id, storages);
1686                }
1687                (component_ids.into(), id)
1688            });
1689        *bundle_id
1690    }
1691
1692    pub(crate) fn init_component_info(
1698        &mut self,
1699        storages: &mut Storages,
1700        components: &Components,
1701        component_id: ComponentId,
1702    ) -> BundleId {
1703        let bundle_infos = &mut self.bundle_infos;
1704        let bundle_id = self
1705            .dynamic_component_bundle_ids
1706            .entry(component_id)
1707            .or_insert_with(|| {
1708                let (id, storage_type) = initialize_dynamic_bundle(
1709                    bundle_infos,
1710                    storages,
1711                    components,
1712                    vec![component_id],
1713                );
1714                self.dynamic_component_storages.insert(id, storage_type[0]);
1715                id
1716            });
1717        *bundle_id
1718    }
1719}
1720
1721fn initialize_dynamic_bundle(
1724    bundle_infos: &mut Vec<BundleInfo>,
1725    storages: &mut Storages,
1726    components: &Components,
1727    component_ids: Vec<ComponentId>,
1728) -> (BundleId, Vec<StorageType>) {
1729    let storage_types = component_ids.iter().map(|&id| {
1731        components.get_info(id).unwrap_or_else(|| {
1732            panic!(
1733                "init_dynamic_info called with component id {id:?} which doesn't exist in this world"
1734            )
1735        }).storage_type()
1736    }).collect();
1737
1738    let id = BundleId(bundle_infos.len());
1739    let bundle_info =
1740        unsafe { BundleInfo::new("<dynamic bundle>", storages, components, component_ids, id) };
1742    bundle_infos.push(bundle_info);
1743
1744    (id, storage_types)
1745}
1746
1747fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
1748    let mut remove_index = 0;
1749    source.retain(|value| {
1750        while remove_index < remove.len() && *value > remove[remove_index] {
1751            remove_index += 1;
1752        }
1753
1754        if remove_index < remove.len() {
1755            *value != remove[remove_index]
1756        } else {
1757            true
1758        }
1759    });
1760}
1761
1762#[cfg(test)]
1763mod tests {
1764    use crate::{component::HookContext, prelude::*, world::DeferredWorld};
1765    use alloc::vec;
1766
1767    #[derive(Component)]
1768    struct A;
1769
1770    #[derive(Component)]
1771    #[component(on_add = a_on_add, on_insert = a_on_insert, on_replace = a_on_replace, on_remove = a_on_remove)]
1772    struct AMacroHooks;
1773
1774    fn a_on_add(mut world: DeferredWorld, _: HookContext) {
1775        world.resource_mut::<R>().assert_order(0);
1776    }
1777
1778    fn a_on_insert(mut world: DeferredWorld, _: HookContext) {
1779        world.resource_mut::<R>().assert_order(1);
1780    }
1781
1782    fn a_on_replace(mut world: DeferredWorld, _: HookContext) {
1783        world.resource_mut::<R>().assert_order(2);
1784    }
1785
1786    fn a_on_remove(mut world: DeferredWorld, _: HookContext) {
1787        world.resource_mut::<R>().assert_order(3);
1788    }
1789
1790    #[derive(Component)]
1791    struct B;
1792
1793    #[derive(Component)]
1794    struct C;
1795
1796    #[derive(Component)]
1797    struct D;
1798
1799    #[derive(Component, Eq, PartialEq, Debug)]
1800    struct V(&'static str); #[derive(Resource, Default)]
1803    struct R(usize);
1804
1805    impl R {
1806        #[track_caller]
1807        fn assert_order(&mut self, count: usize) {
1808            assert_eq!(count, self.0);
1809            self.0 += 1;
1810        }
1811    }
1812
1813    #[test]
1814    fn component_hook_order_spawn_despawn() {
1815        let mut world = World::new();
1816        world.init_resource::<R>();
1817        world
1818            .register_component_hooks::<A>()
1819            .on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
1820            .on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
1821            .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
1822            .on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
1823
1824        let entity = world.spawn(A).id();
1825        world.despawn(entity);
1826        assert_eq!(4, world.resource::<R>().0);
1827    }
1828
1829    #[test]
1830    fn component_hook_order_spawn_despawn_with_macro_hooks() {
1831        let mut world = World::new();
1832        world.init_resource::<R>();
1833
1834        let entity = world.spawn(AMacroHooks).id();
1835        world.despawn(entity);
1836
1837        assert_eq!(4, world.resource::<R>().0);
1838    }
1839
1840    #[test]
1841    fn component_hook_order_insert_remove() {
1842        let mut world = World::new();
1843        world.init_resource::<R>();
1844        world
1845            .register_component_hooks::<A>()
1846            .on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
1847            .on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
1848            .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
1849            .on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
1850
1851        let mut entity = world.spawn_empty();
1852        entity.insert(A);
1853        entity.remove::<A>();
1854        entity.flush();
1855        assert_eq!(4, world.resource::<R>().0);
1856    }
1857
1858    #[test]
1859    fn component_hook_order_replace() {
1860        let mut world = World::new();
1861        world
1862            .register_component_hooks::<A>()
1863            .on_replace(|mut world, _| world.resource_mut::<R>().assert_order(0))
1864            .on_insert(|mut world, _| {
1865                if let Some(mut r) = world.get_resource_mut::<R>() {
1866                    r.assert_order(1);
1867                }
1868            });
1869
1870        let entity = world.spawn(A).id();
1871        world.init_resource::<R>();
1872        let mut entity = world.entity_mut(entity);
1873        entity.insert(A);
1874        entity.insert_if_new(A); entity.flush();
1876        assert_eq!(2, world.resource::<R>().0);
1877    }
1878
1879    #[test]
1880    fn component_hook_order_recursive() {
1881        let mut world = World::new();
1882        world.init_resource::<R>();
1883        world
1884            .register_component_hooks::<A>()
1885            .on_add(|mut world, context| {
1886                world.resource_mut::<R>().assert_order(0);
1887                world.commands().entity(context.entity).insert(B);
1888            })
1889            .on_remove(|mut world, context| {
1890                world.resource_mut::<R>().assert_order(2);
1891                world.commands().entity(context.entity).remove::<B>();
1892            });
1893
1894        world
1895            .register_component_hooks::<B>()
1896            .on_add(|mut world, context| {
1897                world.resource_mut::<R>().assert_order(1);
1898                world.commands().entity(context.entity).remove::<A>();
1899            })
1900            .on_remove(|mut world, _| {
1901                world.resource_mut::<R>().assert_order(3);
1902            });
1903
1904        let entity = world.spawn(A).flush();
1905        let entity = world.get_entity(entity).unwrap();
1906        assert!(!entity.contains::<A>());
1907        assert!(!entity.contains::<B>());
1908        assert_eq!(4, world.resource::<R>().0);
1909    }
1910
1911    #[test]
1912    fn component_hook_order_recursive_multiple() {
1913        let mut world = World::new();
1914        world.init_resource::<R>();
1915        world
1916            .register_component_hooks::<A>()
1917            .on_add(|mut world, context| {
1918                world.resource_mut::<R>().assert_order(0);
1919                world.commands().entity(context.entity).insert(B).insert(C);
1920            });
1921
1922        world
1923            .register_component_hooks::<B>()
1924            .on_add(|mut world, context| {
1925                world.resource_mut::<R>().assert_order(1);
1926                world.commands().entity(context.entity).insert(D);
1927            });
1928
1929        world
1930            .register_component_hooks::<C>()
1931            .on_add(|mut world, _| {
1932                world.resource_mut::<R>().assert_order(3);
1933            });
1934
1935        world
1936            .register_component_hooks::<D>()
1937            .on_add(|mut world, _| {
1938                world.resource_mut::<R>().assert_order(2);
1939            });
1940
1941        world.spawn(A).flush();
1942        assert_eq!(4, world.resource::<R>().0);
1943    }
1944
1945    #[test]
1946    fn insert_if_new() {
1947        let mut world = World::new();
1948        let id = world.spawn(V("one")).id();
1949        let mut entity = world.entity_mut(id);
1950        entity.insert_if_new(V("two"));
1951        entity.insert_if_new((A, V("three")));
1952        entity.flush();
1953        let entity = world.entity(id);
1955        assert!(entity.contains::<A>());
1956        assert_eq!(entity.get(), Some(&V("one")));
1957    }
1958
1959    #[test]
1960    fn sorted_remove() {
1961        let mut a = vec![1, 2, 3, 4, 5, 6, 7];
1962        let b = vec![1, 2, 3, 5, 7];
1963        super::sorted_remove(&mut a, &b);
1964
1965        assert_eq!(a, vec![4, 6]);
1966
1967        let mut a = vec![1];
1968        let b = vec![1];
1969        super::sorted_remove(&mut a, &b);
1970
1971        assert_eq!(a, vec![]);
1972
1973        let mut a = vec![1];
1974        let b = vec![2];
1975        super::sorted_remove(&mut a, &b);
1976
1977        assert_eq!(a, vec![1]);
1978    }
1979}