Skip to main content

bevy_ecs/
lib.rs

1#![doc = "# Bevy ECS\n\n[![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)](https://github.com/bevyengine/bevy#license)\n[![Crates.io](https://img.shields.io/crates/v/bevy_ecs.svg)](https://crates.io/crates/bevy_ecs)\n[![Downloads](https://img.shields.io/crates/d/bevy_ecs.svg)](https://crates.io/crates/bevy_ecs)\n[![Docs](https://docs.rs/bevy_ecs/badge.svg)](https://docs.rs/bevy_ecs/latest/bevy_ecs/)\n[![Discord](https://img.shields.io/discord/691052431525675048.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/bevy)\n\n## What is Bevy ECS?\n\nBevy ECS is an Entity Component System custom-built for the [Bevy][bevy] game engine.\nIt aims to be simple to use, ergonomic, fast, massively parallel, opinionated, and featureful.\nIt was created specifically for Bevy\'s needs, but it can easily be used as a standalone crate in other projects.\n\n## ECS\n\nAll app logic in Bevy uses the Entity Component System paradigm, which is often shortened to ECS. ECS is a software pattern that involves breaking your program up into Entities, Components, and Systems. Entities are unique \"things\" that are assigned groups of Components, which are then processed using Systems.\n\nFor example, one entity might have a `Position` and `Velocity` component, whereas another entity might have a `Position` and `UI` component. You might have a movement system that runs on all entities with a Position and Velocity component.\n\nThe ECS pattern encourages clean, decoupled designs by forcing you to break up your app data and logic into its core components. It also helps make your code faster by optimizing memory access patterns and making parallelism easier.\n\n## Concepts\n\nBevy ECS is Bevy\'s implementation of the ECS pattern. Unlike other Rust ECS implementations, which often require complex lifetimes, traits, builder patterns, or macros, Bevy ECS uses normal Rust data types for all of these concepts:\n\n### Components\n\nComponents are normal Rust structs. They are data stored in a `World` and specific instances of Components correlate to Entities.\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct Position { x: f32, y: f32 }\n```\n\n### Worlds\n\nEntities, Components, and Resources are stored in a `World`. Worlds, much like `std::collections`\'s `HashSet` and `Vec`, expose operations to insert, read, write, and remove the data they store.\n\n```rust\nuse bevy_ecs::world::World;\n\nlet world = World::default();\n```\n\n### Entities\n\nEntities are unique identifiers that correlate to zero or more Components.\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct Position { x: f32, y: f32 }\n#[derive(Component)]\nstruct Velocity { x: f32, y: f32 }\n\nlet mut world = World::new();\n\nlet entity = world\n    .spawn((Position { x: 0.0, y: 0.0 }, Velocity { x: 1.0, y: 0.0 }))\n    .id();\n\nlet entity_ref = world.entity(entity);\nlet position = entity_ref.get::<Position>().unwrap();\nlet velocity = entity_ref.get::<Velocity>().unwrap();\n```\n\n### Systems\n\nSystems are normal Rust functions. Thanks to the Rust type system, Bevy ECS can use function parameter types to determine what data needs to be sent to the system. It also uses this \"data access\" information to determine what Systems can run in parallel with each other.\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct Position { x: f32, y: f32 }\n\nfn print_position(query: Query<(Entity, &Position)>) {\n    for (entity, position) in &query {\n        println!(\"Entity {} is at position: x {}, y {}\", entity, position.x, position.y);\n    }\n}\n```\n\n### Resources\n\nApps often require unique resources, such as asset collections, renderers, audio servers, time, etc. Bevy ECS makes this pattern a first class citizen. `Resource` is a special kind of component that does not belong to any entity. Instead, it is identified uniquely by its type:\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Resource, Default)]\nstruct Time {\n    seconds: f32,\n}\n\nlet mut world = World::new();\n\nworld.insert_resource(Time::default());\n\nlet time = world.get_resource::<Time>().unwrap();\n\n// You can also access resources from Systems\nfn print_time(time: Res<Time>) {\n    println!(\"{}\", time.seconds);\n}\n```\n\n### Schedules\n\nSchedules run a set of Systems according to some execution strategy.\nSystems can be added to any number of System Sets, which are used to control their scheduling metadata.\n\nThe built in \"parallel executor\" considers dependencies between systems and (by default) run as many of them in parallel as possible. This maximizes performance, while keeping the system execution safe. To control the system ordering, define explicit dependencies between systems and their sets.\n\n## Using Bevy ECS\n\nBevy ECS should feel very natural for those familiar with Rust syntax:\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct Position { x: f32, y: f32 }\n#[derive(Component)]\nstruct Velocity { x: f32, y: f32 }\n\n// This system moves each entity with a Position and Velocity component\nfn movement(mut query: Query<(&mut Position, &Velocity)>) {\n    for (mut position, velocity) in &mut query {\n        position.x += velocity.x;\n        position.y += velocity.y;\n    }\n}\n\nfn main() {\n    // Create a new empty World to hold our Entities and Components\n    let mut world = World::new();\n\n    // Spawn an entity with Position and Velocity components\n    world.spawn((\n        Position { x: 0.0, y: 0.0 },\n        Velocity { x: 1.0, y: 0.0 },\n    ));\n\n    // Create a new Schedule, which defines an execution strategy for Systems\n    let mut schedule = Schedule::default();\n\n    // Add our system to the schedule\n    schedule.add_systems(movement);\n\n    // Run the schedule once. If your app has a \"loop\", you would run this once per loop\n    schedule.run(&mut world);\n}\n```\n\n## Features\n\n### Query Filters\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct Position { x: f32, y: f32 }\n#[derive(Component)]\nstruct Player;\n#[derive(Component)]\nstruct Alive;\n\n// Gets the Position component of all Entities with Player component and without the Alive\n// component.\nfn system(query: Query<&Position, (With<Player>, Without<Alive>)>) {\n    for position in &query {\n    }\n}\n```\n\n### Change Detection\n\nBevy ECS tracks _all_ changes to Components and Resources.\n\nQueries can filter for changed Components:\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct Position { x: f32, y: f32 }\n#[derive(Component)]\nstruct Velocity { x: f32, y: f32 }\n\n// Gets the Position component of all Entities whose Velocity has changed since the last run of the System\nfn system_changed(query: Query<&Position, Changed<Velocity>>) {\n    for position in &query {\n    }\n}\n\n// Gets the Position component of all Entities that had a Velocity component added since the last run of the System\nfn system_added(query: Query<&Position, Added<Velocity>>) {\n    for position in &query {\n    }\n}\n```\n\nResources also expose change state:\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Resource)]\nstruct Time(f32);\n\n// Prints \"time changed!\" if the Time resource has changed since the last run of the System\nfn system(time: Res<Time>) {\n    if time.is_changed() {\n        println!(\"time changed!\");\n    }\n}\n```\n\n### Component Storage\n\nBevy ECS supports multiple component storage types.\n\nComponents can be stored in:\n\n* **Tables**: Fast and cache friendly iteration, but slower adding and removing of components. This is the default storage type.\n* **Sparse Sets**: Fast adding and removing of components, but slower iteration.\n\nComponent storage types are configurable, and they default to table storage if the storage is not manually defined.\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Component)]\nstruct TableStoredComponent;\n\n#[derive(Component)]\n#[component(storage = \"SparseSet\")]\nstruct SparseStoredComponent;\n```\n\n### Component Bundles\n\nDefine sets of Components that should be added together.\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Default, Component)]\nstruct Player;\n#[derive(Default, Component)]\nstruct Position { x: f32, y: f32 }\n#[derive(Default, Component)]\nstruct Velocity { x: f32, y: f32 }\n\n#[derive(Bundle, Default)]\nstruct PlayerBundle {\n    player: Player,\n    position: Position,\n    velocity: Velocity,\n}\n\nlet mut world = World::new();\n\n// Spawn a new entity and insert the default PlayerBundle\nworld.spawn(PlayerBundle::default());\n\n// Bundles play well with Rust\'s struct update syntax\nworld.spawn(PlayerBundle {\n    position: Position { x: 1.0, y: 1.0 },\n    ..Default::default()\n});\n```\n\n### Messages\n\nMessages offer a communication channel between one or more systems.\nThey can be sent using the `MessageWriter` system parameter and received with `MessageReader`.\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Message)]\nstruct Message(String);\n\nfn writer(mut writer: MessageWriter<Message>) {\n    writer.write(Message(\"Hello!\".to_string()));\n}\n\nfn reader(mut reader: MessageReader<Message>) {\n    for Message(message) in reader.read() {\n        println!(\"{}\", message);\n    }\n}\n```\n\n### Observers\n\nObservers are systems that watch for a \"trigger\" of a specific `Event`:\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(Event)]\nstruct Speak {\n    message: String\n}\n\nlet mut world = World::new();\n\nworld.add_observer(|event: On<Speak>| {\n    println!(\"{}\", event.message);\n});\n\nworld.trigger(Speak {\n    message: \"Hello!\".to_string(),\n});\n```\n\nThese differ from `MessageReader` and `MessageWriter` in that they are \"reactive\".\nRather than happening at a specific point in a schedule, they happen _immediately_ whenever a trigger happens.\nTriggers can trigger other triggers, and they all will be evaluated at the same time!\n\nIf the event is an `EntityEvent`, it can also be triggered to target specific entities:\n\n```rust\nuse bevy_ecs::prelude::*;\n\n#[derive(EntityEvent)]\nstruct Explode {\n    entity: Entity,\n}\n\nlet mut world = World::new();\nlet entity = world.spawn_empty().id();\n\nworld.add_observer(|explode: On<Explode>, mut commands: Commands| {\n    println!(\"Entity {} goes BOOM!\", explode.entity);\n    commands.entity(explode.entity).despawn();\n});\n\nworld.trigger(Explode { entity });\n```\n\n[bevy]: https://bevy.org/\n"include_str!("../README.md")]
2#![cfg_attr(
3    any(docsrs, docsrs_dep),
4    expect(
5        internal_features,
6        reason = "rustdoc_internals is needed for fake_variadic"
7    )
8)]
9#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
10#![cfg_attr(docsrs, feature(doc_cfg))]
11#![expect(unsafe_code, reason = "Unsafe code is used to improve performance.")]
12#![doc(
13    html_logo_url = "https://bevy.org/assets/icon.png",
14    html_favicon_url = "https://bevy.org/assets/icon.png"
15)]
16#![no_std]
17
18#[cfg(feature = "std")]
19extern crate std;
20
21#[cfg(target_pointer_width = "16")]
22compile_error!("bevy_ecs cannot safely compile for a 16-bit platform.");
23
24extern crate alloc;
25
26// Required to make proc macros work in bevy itself.
27extern crate self as bevy_ecs;
28
29pub mod archetype;
30pub mod batching;
31pub mod bundle;
32pub mod change_detection;
33pub mod component;
34pub mod entity;
35pub mod entity_disabling;
36pub mod error;
37pub mod event;
38pub mod hierarchy;
39pub mod intern;
40pub mod label;
41pub mod lifecycle;
42pub mod message;
43pub mod name;
44pub mod never;
45pub mod observer;
46pub mod query;
47#[cfg(feature = "bevy_reflect")]
48pub mod reflect;
49pub mod relationship;
50pub mod resource;
51pub mod schedule;
52pub mod spawn;
53pub mod storage;
54pub mod system;
55pub mod template;
56pub mod traversal;
57pub mod world;
58
59pub use bevy_ptr as ptr;
60
61#[cfg(feature = "hotpatching")]
62use message::Message;
63
64/// The ECS prelude.
65///
66/// This includes the most common types in this crate, re-exported for your convenience.
67pub mod prelude {
68    #[doc(hidden)]
69    pub use crate::{
70        bundle::Bundle,
71        change_detection::{
72            ContiguousMut, ContiguousRef, DetectChanges, DetectChangesMut, Mut, Ref,
73        },
74        children,
75        component::Component,
76        entity::{ContainsEntity, Entity, EntityMapper},
77        error::{BevyError, Result, ResultSeverityExt, Severity},
78        event::{EntityEvent, Event},
79        hierarchy::{ChildOf, ChildSpawner, ChildSpawnerCommands, Children},
80        lifecycle::{Add, Despawn, Discard, Insert, Remove, RemovedComponents},
81        message::{
82            Message, MessageMutator, MessageReader, MessageWriter, Messages, PopulatedMessageReader,
83        },
84        name::{Name, NameOrEntity},
85        observer::{Observer, ObserverSystemExt, On},
86        query::{Added, Allow, AnyOf, Changed, Has, Or, QueryBuilder, QueryState, With, Without},
87        related,
88        relationship::RelationshipTarget,
89        resource::Resource,
90        schedule::{
91            common_conditions::*, ApplyDeferred, IntoScheduleConfigs, IntoSystemSet, Schedule,
92            Schedules, SystemCondition, SystemSet,
93        },
94        spawn::{Spawn, SpawnIter, SpawnRelated, SpawnWith, WithOneRelated, WithRelated},
95        system::{
96            Command, Commands, Deferred, EntityCommand, EntityCommands, If, In, InMut, InRef,
97            IntoSystem, Local, NonSend, NonSendMut, ParamSet, Populated, Query, ReadOnlySystem,
98            Res, ResMut, Single, System, SystemIn, SystemInput, SystemParamBuilder,
99            SystemParamFunction,
100        },
101        template::{template, FromTemplate, Template},
102        world::{
103            EntityMut, EntityRef, EntityWorldMut, FilteredResources, FilteredResourcesMut,
104            FromWorld, World,
105        },
106    };
107
108    #[doc(hidden)]
109    #[cfg(feature = "std")]
110    pub use crate::system::ParallelCommands;
111
112    #[doc(hidden)]
113    #[cfg(feature = "bevy_reflect")]
114    pub use crate::reflect::{
115        AppTypeRegistry, ReflectComponent, ReflectEvent, ReflectFromWorld, ReflectMessage,
116        ReflectResource,
117    };
118
119    #[doc(hidden)]
120    #[cfg(feature = "reflect_functions")]
121    pub use crate::reflect::AppFunctionRegistry;
122}
123
124pub use bevy_ecs_macros::VariantDefaults;
125
126/// Exports used by macros.
127///
128/// These are not meant to be used directly and are subject to breaking changes.
129#[doc(hidden)]
130pub mod __macro_exports {
131    // Cannot directly use `alloc::vec::Vec` in macros, as a crate may not have
132    // included `extern crate alloc;`. This re-export ensures we have access
133    // to `Vec` in `no_std` and `std` contexts.
134    pub use crate::query::DebugCheckedUnwrap;
135    pub use alloc::vec::Vec;
136}
137
138/// Event sent when a hotpatch happens.
139///
140/// Can be used for causing custom behavior on hot-patch.
141#[cfg(feature = "hotpatching")]
142#[derive(impl bevy_ecs::message::Message for HotPatched where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}Message, #[automatically_derived]
impl ::core::default::Default for HotPatched {
    #[inline]
    fn default() -> HotPatched { HotPatched {} }
}Default)]
143pub struct HotPatched;
144
145/// Resource which "changes" when a hotpatch happens.
146///
147/// Exists solely for change-detection, which allows systems to
148/// know whether a hotpatch happened even if they only run irregularily and would
149/// miss the event.
150///
151/// Used by Executors and other places which run systems
152/// [`System::refresh_hotpatch`](crate::system::System::refresh_hotpatch) only when necessary.
153#[cfg(feature = "hotpatching")]
154#[derive(impl bevy_ecs::resource::Resource for HotPatchChanges where
    Self: ::core::marker::Send + ::core::marker::Sync + 'static {}resource::Resource, #[automatically_derived]
impl ::core::default::Default for HotPatchChanges {
    #[inline]
    fn default() -> HotPatchChanges { HotPatchChanges {} }
}Default)]
155pub struct HotPatchChanges;
156
157#[cfg(test)]
158mod tests {
159    use crate::{
160        bundle::Bundle,
161        change_detection::Ref,
162        component::Component,
163        entity::{Entity, EntityHashSet, EntityMapper, EntityNotSpawnedError},
164        entity_disabling::DefaultQueryFilters,
165        prelude::Or,
166        query::{Added, Changed, FilteredAccess, QueryFilter, With, Without},
167        resource::Resource,
168        world::{error::EntityDespawnError, EntityMut, EntityRef, Mut, World},
169    };
170    use alloc::{string::String, sync::Arc, vec, vec::Vec};
171    use bevy_platform::collections::HashSet;
172    use bevy_tasks::{ComputeTaskPool, TaskPool};
173    use core::{
174        any::TypeId,
175        marker::PhantomData,
176        sync::atomic::{AtomicUsize, Ordering},
177    };
178    use std::sync::Mutex;
179
180    #[derive(Component, Debug, PartialEq, Eq, Hash, Clone, Copy)]
181    struct A(usize);
182    #[derive(Resource, Debug, PartialEq, Eq)]
183    struct ResA(usize);
184    #[derive(Component, Debug, PartialEq, Eq, Hash, Clone, Copy)]
185    struct B(usize);
186    #[derive(Component, Debug, PartialEq, Eq, Clone, Copy)]
187    struct C;
188
189    #[derive(Default)]
190    struct NonSendA(PhantomData<*mut ()>);
191
192    #[derive(Component, Clone, Debug)]
193    struct DropCk(Arc<AtomicUsize>);
194    impl DropCk {
195        fn new_pair() -> (Self, Arc<AtomicUsize>) {
196            let atomic = Arc::new(AtomicUsize::new(0));
197            (DropCk(atomic.clone()), atomic)
198        }
199    }
200
201    impl Drop for DropCk {
202        fn drop(&mut self) {
203            self.0.as_ref().fetch_add(1, Ordering::Relaxed);
204        }
205    }
206
207    #[expect(
208        dead_code,
209        reason = "This struct is used to test how `Drop` behavior works in regards to SparseSet storage, and as such is solely a wrapper around `DropCk` to make it use the SparseSet storage. Because of this, the inner field is intentionally never read."
210    )]
211    #[derive(Component, Clone, Debug)]
212    #[component(storage = "SparseSet")]
213    struct DropCkSparse(DropCk);
214
215    #[derive(Component, Copy, Clone, PartialEq, Eq, Debug)]
216    #[component(storage = "Table")]
217    struct TableStored(&'static str);
218    #[derive(Component, Copy, Clone, PartialEq, Eq, Hash, Debug)]
219    #[component(storage = "SparseSet")]
220    struct SparseStored(u32);
221
222    #[test]
223    fn random_access() {
224        let mut world = World::new();
225
226        let e = world.spawn((TableStored("abc"), SparseStored(123))).id();
227        let f = world
228            .spawn((TableStored("def"), SparseStored(456), A(1)))
229            .id();
230        assert_eq!(world.get::<TableStored>(e).unwrap().0, "abc");
231        assert_eq!(world.get::<SparseStored>(e).unwrap().0, 123);
232        assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
233        assert_eq!(world.get::<SparseStored>(f).unwrap().0, 456);
234
235        // test archetype get_mut()
236        world.get_mut::<TableStored>(e).unwrap().0 = "xyz";
237        assert_eq!(world.get::<TableStored>(e).unwrap().0, "xyz");
238
239        // test sparse set get_mut()
240        world.get_mut::<SparseStored>(f).unwrap().0 = 42;
241        assert_eq!(world.get::<SparseStored>(f).unwrap().0, 42);
242    }
243
244    #[test]
245    fn bundle_derive() {
246        let mut world = World::new();
247
248        #[derive(Bundle, PartialEq, Debug)]
249        struct FooBundle {
250            x: TableStored,
251            y: SparseStored,
252        }
253        let ids: Vec<_> =
254            <FooBundle as Bundle>::component_ids(&mut world.components_registrator()).collect();
255
256        assert_eq!(
257            ids,
258            &[
259                world.register_component::<TableStored>(),
260                world.register_component::<SparseStored>(),
261            ]
262        );
263
264        let e1 = world
265            .spawn(FooBundle {
266                x: TableStored("abc"),
267                y: SparseStored(123),
268            })
269            .id();
270        let e2 = world
271            .spawn((TableStored("def"), SparseStored(456), A(1)))
272            .id();
273        assert_eq!(world.get::<TableStored>(e1).unwrap().0, "abc");
274        assert_eq!(world.get::<SparseStored>(e1).unwrap().0, 123);
275        assert_eq!(world.get::<TableStored>(e2).unwrap().0, "def");
276        assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 456);
277
278        // test archetype get_mut()
279        world.get_mut::<TableStored>(e1).unwrap().0 = "xyz";
280        assert_eq!(world.get::<TableStored>(e1).unwrap().0, "xyz");
281
282        // test sparse set get_mut()
283        world.get_mut::<SparseStored>(e2).unwrap().0 = 42;
284        assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 42);
285
286        assert_eq!(
287            world.entity_mut(e1).take::<FooBundle>().unwrap(),
288            FooBundle {
289                x: TableStored("xyz"),
290                y: SparseStored(123),
291            }
292        );
293
294        #[derive(Bundle, PartialEq, Debug)]
295        struct NestedBundle {
296            a: A,
297            foo: FooBundle,
298            b: B,
299        }
300
301        let ids: Vec<_> =
302            <NestedBundle as Bundle>::component_ids(&mut world.components_registrator()).collect();
303
304        assert_eq!(
305            ids,
306            &[
307                world.register_component::<A>(),
308                world.register_component::<TableStored>(),
309                world.register_component::<SparseStored>(),
310                world.register_component::<B>(),
311            ]
312        );
313
314        let e3 = world
315            .spawn(NestedBundle {
316                a: A(1),
317                foo: FooBundle {
318                    x: TableStored("ghi"),
319                    y: SparseStored(789),
320                },
321                b: B(2),
322            })
323            .id();
324
325        assert_eq!(world.get::<TableStored>(e3).unwrap().0, "ghi");
326        assert_eq!(world.get::<SparseStored>(e3).unwrap().0, 789);
327        assert_eq!(world.get::<A>(e3).unwrap().0, 1);
328        assert_eq!(world.get::<B>(e3).unwrap().0, 2);
329        assert_eq!(
330            world.entity_mut(e3).take::<NestedBundle>().unwrap(),
331            NestedBundle {
332                a: A(1),
333                foo: FooBundle {
334                    x: TableStored("ghi"),
335                    y: SparseStored(789),
336                },
337                b: B(2),
338            }
339        );
340
341        #[derive(Default, Component, PartialEq, Debug)]
342        struct Ignored;
343
344        #[derive(Bundle, PartialEq, Debug)]
345        struct BundleWithIgnored {
346            c: C,
347            #[bundle(ignore)]
348            ignored: Ignored,
349        }
350
351        let ids: Vec<_> =
352            <BundleWithIgnored as Bundle>::component_ids(&mut world.components_registrator())
353                .collect();
354
355        assert_eq!(ids, &[world.register_component::<C>(),]);
356
357        let e4 = world
358            .spawn(BundleWithIgnored {
359                c: C,
360                ignored: Ignored,
361            })
362            .id();
363
364        assert_eq!(world.get::<C>(e4).unwrap(), &C);
365        assert_eq!(world.get::<Ignored>(e4), None);
366
367        assert_eq!(
368            world.entity_mut(e4).take::<BundleWithIgnored>().unwrap(),
369            BundleWithIgnored {
370                c: C,
371                ignored: Ignored,
372            }
373        );
374    }
375
376    #[test]
377    fn spawning_with_manual_entity_allocation() {
378        let mut world = World::new();
379        let start = world.entities().count_spawned();
380        let e1 = world.entity_allocator_mut().alloc();
381        world.spawn_at(e1, (TableStored("abc"), A(123))).unwrap();
382
383        let e2 = world.entity_allocator_mut().alloc();
384        assert!(matches!(
385            world.try_despawn_no_free(e2),
386            Err(EntityDespawnError(
387                EntityNotSpawnedError::ValidButNotSpawned(_)
388            ))
389        ));
390        assert!(!world.despawn(e2));
391        world.entity_allocator_mut().free(e2);
392
393        let e3 = world.entity_allocator_mut().alloc();
394        let e3 = world
395            .spawn_at(e3, (TableStored("junk"), A(0)))
396            .unwrap()
397            .despawn_no_free();
398        world.spawn_at(e3, (TableStored("def"), A(456))).unwrap();
399
400        assert_eq!(world.entities.count_spawned(), start + 2);
401        assert!(world.despawn(e1));
402        assert_eq!(world.entities.count_spawned(), start + 1);
403        assert!(world.get::<TableStored>(e1).is_none());
404        assert!(world.get::<A>(e1).is_none());
405        assert_eq!(world.get::<TableStored>(e3).unwrap().0, "def");
406        assert_eq!(world.get::<A>(e3).unwrap().0, 456);
407    }
408
409    #[test]
410    fn despawn_table_storage() {
411        let mut world = World::new();
412        let e = world.spawn((TableStored("abc"), A(123))).id();
413        let f = world.spawn((TableStored("def"), A(456))).id();
414        assert_eq!(world.query::<&TableStored>().query(&world).count(), 2);
415        assert!(world.despawn(e));
416        assert_eq!(world.query::<&TableStored>().query(&world).count(), 1);
417        assert!(world.get::<TableStored>(e).is_none());
418        assert!(world.get::<A>(e).is_none());
419        assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
420        assert_eq!(world.get::<A>(f).unwrap().0, 456);
421    }
422
423    #[test]
424    fn despawn_mixed_storage() {
425        let mut world = World::new();
426
427        let e = world.spawn((TableStored("abc"), SparseStored(123))).id();
428        let f = world.spawn((TableStored("def"), SparseStored(456))).id();
429        assert_eq!(world.query::<&TableStored>().query(&world).count(), 2);
430        assert!(world.despawn(e));
431        assert_eq!(world.query::<&TableStored>().query(&world).count(), 1);
432        assert!(world.get::<TableStored>(e).is_none());
433        assert!(world.get::<SparseStored>(e).is_none());
434        assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
435        assert_eq!(world.get::<SparseStored>(f).unwrap().0, 456);
436    }
437
438    #[test]
439    fn query_all() {
440        let mut world = World::new();
441        let e = world.spawn((TableStored("abc"), A(123))).id();
442        let f = world.spawn((TableStored("def"), A(456))).id();
443
444        let ents = world
445            .query::<(Entity, &A, &TableStored)>()
446            .iter(&world)
447            .map(|(e, &i, &s)| (e, i, s))
448            .collect::<Vec<_>>();
449        assert_eq!(
450            ents,
451            &[
452                (e, A(123), TableStored("abc")),
453                (f, A(456), TableStored("def"))
454            ]
455        );
456    }
457
458    #[test]
459    fn query_all_for_each() {
460        let mut world = World::new();
461        let e = world.spawn((TableStored("abc"), A(123))).id();
462        let f = world.spawn((TableStored("def"), A(456))).id();
463
464        let mut results = Vec::new();
465        world
466            .query::<(Entity, &A, &TableStored)>()
467            .iter(&world)
468            .for_each(|(e, &i, &s)| results.push((e, i, s)));
469        assert_eq!(
470            results,
471            &[
472                (e, A(123), TableStored("abc")),
473                (f, A(456), TableStored("def"))
474            ]
475        );
476    }
477
478    #[test]
479    fn query_single_component() {
480        let mut world = World::new();
481        let e = world.spawn((TableStored("abc"), A(123))).id();
482        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
483        let ents = world
484            .query::<(Entity, &A)>()
485            .iter(&world)
486            .map(|(e, &i)| (e, i))
487            .collect::<HashSet<_>>();
488        assert!(ents.contains(&(e, A(123))));
489        assert!(ents.contains(&(f, A(456))));
490    }
491
492    #[test]
493    fn stateful_query_handles_new_archetype() {
494        let mut world = World::new();
495        let e = world.spawn((TableStored("abc"), A(123))).id();
496        let mut query = world.query::<(Entity, &A)>();
497
498        let ents = query.iter(&world).map(|(e, &i)| (e, i)).collect::<Vec<_>>();
499        assert_eq!(ents, &[(e, A(123))]);
500
501        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
502        let ents = query.iter(&world).map(|(e, &i)| (e, i)).collect::<Vec<_>>();
503        assert_eq!(ents, &[(e, A(123)), (f, A(456))]);
504    }
505
506    #[test]
507    fn query_single_component_for_each() {
508        let mut world = World::new();
509        let e = world.spawn((TableStored("abc"), A(123))).id();
510        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
511        let mut results = <HashSet<_>>::default();
512        world
513            .query::<(Entity, &A)>()
514            .iter(&world)
515            .for_each(|(e, &i)| {
516                results.insert((e, i));
517            });
518        assert!(results.contains(&(e, A(123))));
519        assert!(results.contains(&(f, A(456))));
520    }
521
522    #[test]
523    fn par_for_each_dense() {
524        ComputeTaskPool::get_or_init(TaskPool::default);
525        let mut world = World::new();
526        let e1 = world.spawn(A(1)).id();
527        let e2 = world.spawn(A(2)).id();
528        let e3 = world.spawn(A(3)).id();
529        let e4 = world.spawn((A(4), B(1))).id();
530        let e5 = world.spawn((A(5), B(1))).id();
531        let results = Arc::new(Mutex::new(Vec::new()));
532        world
533            .query::<(Entity, &A)>()
534            .par_iter(&world)
535            .for_each(|(e, &A(i))| {
536                results.lock().unwrap().push((e, i));
537            });
538        results.lock().unwrap().sort();
539        let mut expected = [(e1, 1), (e2, 2), (e3, 3), (e4, 4), (e5, 5)];
540        expected.sort();
541        assert_eq!(&*results.lock().unwrap(), &expected);
542    }
543
544    #[test]
545    fn par_for_each_sparse() {
546        ComputeTaskPool::get_or_init(TaskPool::default);
547        let mut world = World::new();
548        let e1 = world.spawn(SparseStored(1)).id();
549        let e2 = world.spawn(SparseStored(2)).id();
550        let e3 = world.spawn(SparseStored(3)).id();
551        let e4 = world.spawn((SparseStored(4), A(1))).id();
552        let e5 = world.spawn((SparseStored(5), A(1))).id();
553        let results = Arc::new(Mutex::new(Vec::new()));
554        world
555            .query::<(Entity, &SparseStored)>()
556            .par_iter(&world)
557            .for_each(|(e, &SparseStored(i))| results.lock().unwrap().push((e, i)));
558        results.lock().unwrap().sort();
559        let mut expected = [(e1, 1), (e2, 2), (e3, 3), (e4, 4), (e5, 5)];
560        expected.sort();
561        assert_eq!(&*results.lock().unwrap(), &expected);
562    }
563
564    #[test]
565    fn query_missing_component() {
566        let mut world = World::new();
567        world.spawn((TableStored("abc"), A(123)));
568        world.spawn((TableStored("def"), A(456)));
569        assert!(world.query::<(&B, &A)>().iter(&world).next().is_none());
570    }
571
572    #[test]
573    fn query_sparse_component() {
574        let mut world = World::new();
575        world.spawn((TableStored("abc"), A(123)));
576        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
577        let ents = world
578            .query::<(Entity, &B)>()
579            .iter(&world)
580            .map(|(e, &b)| (e, b))
581            .collect::<Vec<_>>();
582        assert_eq!(ents, &[(f, B(1))]);
583    }
584
585    #[test]
586    fn query_filter_with() {
587        let mut world = World::new();
588        world.spawn((A(123), B(1)));
589        world.spawn(A(456));
590        let result = world
591            .query_filtered::<&A, With<B>>()
592            .iter(&world)
593            .cloned()
594            .collect::<Vec<_>>();
595        assert_eq!(result, vec![A(123)]);
596    }
597
598    #[test]
599    fn query_filter_with_for_each() {
600        let mut world = World::new();
601        world.spawn((A(123), B(1)));
602        world.spawn(A(456));
603
604        let mut results = Vec::new();
605        world
606            .query_filtered::<&A, With<B>>()
607            .iter(&world)
608            .for_each(|i| results.push(*i));
609        assert_eq!(results, vec![A(123)]);
610    }
611
612    #[test]
613    fn query_filter_with_sparse() {
614        let mut world = World::new();
615
616        world.spawn((A(123), SparseStored(321)));
617        world.spawn(A(456));
618        let result = world
619            .query_filtered::<&A, With<SparseStored>>()
620            .iter(&world)
621            .cloned()
622            .collect::<Vec<_>>();
623        assert_eq!(result, vec![A(123)]);
624    }
625
626    #[test]
627    fn query_filter_with_sparse_for_each() {
628        let mut world = World::new();
629
630        world.spawn((A(123), SparseStored(321)));
631        world.spawn(A(456));
632        let mut results = Vec::new();
633        world
634            .query_filtered::<&A, With<SparseStored>>()
635            .iter(&world)
636            .for_each(|i| results.push(*i));
637        assert_eq!(results, vec![A(123)]);
638    }
639
640    #[test]
641    fn query_filter_without() {
642        let mut world = World::new();
643        world.spawn((A(123), B(321)));
644        world.spawn(A(456));
645        let result = world
646            .query_filtered::<&A, Without<B>>()
647            .iter(&world)
648            .cloned()
649            .collect::<Vec<_>>();
650        assert_eq!(result, vec![A(456)]);
651    }
652
653    #[test]
654    fn query_optional_component_table() {
655        let mut world = World::new();
656        let e = world.spawn((TableStored("abc"), A(123))).id();
657        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
658        // this should be skipped
659        world.spawn(TableStored("abc"));
660        let ents = world
661            .query::<(Entity, Option<&B>, &A)>()
662            .iter(&world)
663            .map(|(e, b, &i)| (e, b.copied(), i))
664            .collect::<HashSet<_>>();
665        assert!(ents.contains(&(e, None, A(123))));
666        assert!(ents.contains(&(f, Some(B(1)), A(456))));
667    }
668
669    #[test]
670    fn query_optional_component_sparse() {
671        let mut world = World::new();
672
673        let e = world.spawn((TableStored("abc"), A(123))).id();
674        let f = world
675            .spawn((TableStored("def"), A(456), SparseStored(1)))
676            .id();
677        // this should be skipped
678        // world.spawn(SparseStored(1));
679        let ents = world
680            .query::<(Entity, Option<&SparseStored>, &A)>()
681            .iter(&world)
682            .map(|(e, b, &i)| (e, b.copied(), i))
683            .collect::<HashSet<_>>();
684        assert_eq!(
685            ents,
686            [(e, None, A(123)), (f, Some(SparseStored(1)), A(456))]
687                .into_iter()
688                .collect::<HashSet<_>>()
689        );
690    }
691
692    #[test]
693    fn query_optional_component_sparse_no_match() {
694        let mut world = World::new();
695
696        let e = world.spawn((TableStored("abc"), A(123))).id();
697        let f = world.spawn((TableStored("def"), A(456))).id();
698        // // this should be skipped
699        world.spawn(TableStored("abc"));
700        let ents = world
701            .query::<(Entity, Option<&SparseStored>, &A)>()
702            .iter(&world)
703            .map(|(e, b, &i)| (e, b.copied(), i))
704            .collect::<Vec<_>>();
705        assert_eq!(ents, &[(e, None, A(123)), (f, None, A(456))]);
706    }
707
708    #[test]
709    fn add_remove_components() {
710        let mut world = World::new();
711        let e1 = world.spawn((A(1), B(3), TableStored("abc"))).id();
712        let e2 = world.spawn((A(2), B(4), TableStored("xyz"))).id();
713
714        assert_eq!(
715            world
716                .query::<(Entity, &A, &B)>()
717                .iter(&world)
718                .map(|(e, &i, &b)| (e, i, b))
719                .collect::<HashSet<_>>(),
720            [(e1, A(1), B(3)), (e2, A(2), B(4))]
721                .into_iter()
722                .collect::<HashSet<_>>()
723        );
724        assert_eq!(world.entity_mut(e1).take::<A>(), Some(A(1)));
725        assert_eq!(
726            world
727                .query::<(Entity, &A, &B)>()
728                .iter(&world)
729                .map(|(e, &i, &b)| (e, i, b))
730                .collect::<Vec<_>>(),
731            &[(e2, A(2), B(4))]
732        );
733        assert_eq!(
734            world
735                .query::<(Entity, &B, &TableStored)>()
736                .iter(&world)
737                .map(|(e, &B(b), &TableStored(s))| (e, b, s))
738                .collect::<HashSet<_>>(),
739            [(e2, 4, "xyz"), (e1, 3, "abc")]
740                .into_iter()
741                .collect::<HashSet<_>>()
742        );
743        world.entity_mut(e1).insert(A(43));
744        assert_eq!(
745            world
746                .query::<(Entity, &A, &B)>()
747                .iter(&world)
748                .map(|(e, &i, &b)| (e, i, b))
749                .collect::<HashSet<_>>(),
750            [(e2, A(2), B(4)), (e1, A(43), B(3))]
751                .into_iter()
752                .collect::<HashSet<_>>()
753        );
754        world.entity_mut(e1).insert(C);
755        assert_eq!(
756            world
757                .query::<(Entity, &C)>()
758                .iter(&world)
759                .map(|(e, &f)| (e, f))
760                .collect::<Vec<_>>(),
761            &[(e1, C)]
762        );
763    }
764
765    #[test]
766    fn table_add_remove_many() {
767        let mut world = World::default();
768        #[cfg(miri)]
769        let (mut entities, to) = {
770            let to = 10;
771            (Vec::with_capacity(to), to)
772        };
773        #[cfg(not(miri))]
774        let (mut entities, to) = {
775            let to = 10_000;
776            (Vec::with_capacity(to), to)
777        };
778
779        for _ in 0..to {
780            entities.push(world.spawn(B(0)).id());
781        }
782
783        for (i, entity) in entities.iter().cloned().enumerate() {
784            world.entity_mut(entity).insert(A(i));
785        }
786
787        for (i, entity) in entities.iter().cloned().enumerate() {
788            assert_eq!(world.entity_mut(entity).take::<A>(), Some(A(i)));
789        }
790    }
791
792    #[test]
793    fn sparse_set_add_remove_many() {
794        let mut world = World::default();
795
796        let mut entities = Vec::with_capacity(1000);
797        for _ in 0..4 {
798            entities.push(world.spawn(A(2)).id());
799        }
800
801        for (i, entity) in entities.iter().cloned().enumerate() {
802            world.entity_mut(entity).insert(SparseStored(i as u32));
803        }
804
805        for (i, entity) in entities.iter().cloned().enumerate() {
806            assert_eq!(
807                world.entity_mut(entity).take::<SparseStored>(),
808                Some(SparseStored(i as u32))
809            );
810        }
811    }
812
813    #[test]
814    fn remove_missing() {
815        let mut world = World::new();
816        let e = world.spawn((TableStored("abc"), A(123))).id();
817        assert!(world.entity_mut(e).take::<B>().is_none());
818    }
819
820    #[test]
821    fn spawn_batch() {
822        let mut world = World::new();
823        world.spawn_batch((0..100).map(|x| (A(x), TableStored("abc"))));
824        let values = world
825            .query::<&A>()
826            .iter(&world)
827            .map(|v| v.0)
828            .collect::<Vec<_>>();
829        let expected = (0..100).collect::<Vec<_>>();
830        assert_eq!(values, expected);
831    }
832
833    #[test]
834    fn query_get() {
835        let mut world = World::new();
836        let a = world.spawn((TableStored("abc"), A(123))).id();
837        let b = world.spawn((TableStored("def"), A(456))).id();
838        let c = world.spawn((TableStored("ghi"), A(789), B(1))).id();
839
840        let mut i32_query = world.query::<&A>();
841        assert_eq!(i32_query.get(&world, a).unwrap().0, 123);
842        assert_eq!(i32_query.get(&world, b).unwrap().0, 456);
843
844        let mut i32_bool_query = world.query::<(&A, &B)>();
845        assert!(i32_bool_query.get(&world, a).is_err());
846        assert_eq!(i32_bool_query.get(&world, c).unwrap(), (&A(789), &B(1)));
847        assert!(world.despawn(a));
848        assert!(i32_query.get(&world, a).is_err());
849    }
850
851    #[test]
852    fn query_get_works_across_sparse_removal() {
853        // Regression test for: https://github.com/bevyengine/bevy/issues/6623
854        let mut world = World::new();
855        let a = world.spawn((TableStored("abc"), SparseStored(123))).id();
856        let b = world.spawn((TableStored("def"), SparseStored(456))).id();
857        let c = world
858            .spawn((TableStored("ghi"), SparseStored(789), B(1)))
859            .id();
860
861        let mut query = world.query::<&TableStored>();
862        assert_eq!(query.get(&world, a).unwrap(), &TableStored("abc"));
863        assert_eq!(query.get(&world, b).unwrap(), &TableStored("def"));
864        assert_eq!(query.get(&world, c).unwrap(), &TableStored("ghi"));
865
866        world.entity_mut(b).remove::<SparseStored>();
867        world.entity_mut(c).remove::<SparseStored>();
868
869        assert_eq!(query.get(&world, a).unwrap(), &TableStored("abc"));
870        assert_eq!(query.get(&world, b).unwrap(), &TableStored("def"));
871        assert_eq!(query.get(&world, c).unwrap(), &TableStored("ghi"));
872    }
873
874    #[test]
875    fn remove_tracking() {
876        let mut world = World::new();
877
878        let a = world.spawn((SparseStored(0), A(123))).id();
879        let b = world.spawn((SparseStored(1), A(123))).id();
880
881        world.entity_mut(a).despawn();
882        assert_eq!(
883            world.removed::<A>().collect::<Vec<_>>(),
884            &[a],
885            "despawning results in 'removed component' state for table components"
886        );
887        assert_eq!(
888            world.removed::<SparseStored>().collect::<Vec<_>>(),
889            &[a],
890            "despawning results in 'removed component' state for sparse set components"
891        );
892
893        world.entity_mut(b).insert(B(1));
894        assert_eq!(
895            world.removed::<A>().collect::<Vec<_>>(),
896            &[a],
897            "archetype moves does not result in 'removed component' state"
898        );
899
900        world.entity_mut(b).remove::<A>();
901        assert_eq!(
902            world.removed::<A>().collect::<Vec<_>>(),
903            &[a, b],
904            "removing a component results in a 'removed component' state"
905        );
906
907        world.clear_trackers();
908        assert_eq!(
909            world.removed::<A>().collect::<Vec<_>>(),
910            &[],
911            "clearing trackers clears removals"
912        );
913        assert_eq!(
914            world.removed::<SparseStored>().collect::<Vec<_>>(),
915            &[],
916            "clearing trackers clears removals"
917        );
918        assert_eq!(
919            world.removed::<B>().collect::<Vec<_>>(),
920            &[],
921            "clearing trackers clears removals"
922        );
923
924        // TODO: uncomment when world.clear() is implemented
925        // let c = world.spawn(("abc", 123)).id();
926        // let d = world.spawn(("abc", 123)).id();
927        // world.clear();
928        // assert_eq!(
929        //     world.removed::<i32>(),
930        //     &[c, d],
931        //     "world clears result in 'removed component' states"
932        // );
933        // assert_eq!(
934        //     world.removed::<&'static str>(),
935        //     &[c, d, b],
936        //     "world clears result in 'removed component' states"
937        // );
938        // assert_eq!(
939        //     world.removed::<f64>(),
940        //     &[b],
941        //     "world clears result in 'removed component' states"
942        // );
943    }
944
945    #[test]
946    fn added_tracking() {
947        let mut world = World::new();
948        let a = world.spawn(A(123)).id();
949
950        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
951        assert_eq!(
952            world.query_filtered::<(), Added<A>>().iter(&world).count(),
953            1
954        );
955        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
956        assert_eq!(
957            world.query_filtered::<(), Added<A>>().iter(&world).count(),
958            1
959        );
960        assert!(world.query::<&A>().get(&world, a).is_ok());
961        assert!(world
962            .query_filtered::<(), Added<A>>()
963            .get(&world, a)
964            .is_ok());
965        assert!(world.query::<&A>().get(&world, a).is_ok());
966        assert!(world
967            .query_filtered::<(), Added<A>>()
968            .get(&world, a)
969            .is_ok());
970
971        world.clear_trackers();
972
973        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
974        assert_eq!(
975            world.query_filtered::<(), Added<A>>().iter(&world).count(),
976            0
977        );
978        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
979        assert_eq!(
980            world.query_filtered::<(), Added<A>>().iter(&world).count(),
981            0
982        );
983        assert!(world.query::<&A>().get(&world, a).is_ok());
984        assert!(world
985            .query_filtered::<(), Added<A>>()
986            .get(&world, a)
987            .is_err());
988        assert!(world.query::<&A>().get(&world, a).is_ok());
989        assert!(world
990            .query_filtered::<(), Added<A>>()
991            .get(&world, a)
992            .is_err());
993    }
994
995    #[test]
996    fn added_queries() {
997        let mut world = World::default();
998        let e1 = world.spawn(A(0)).id();
999
1000        fn get_added<Com: Component>(world: &mut World) -> Vec<Entity> {
1001            world
1002                .query_filtered::<Entity, Added<Com>>()
1003                .iter(world)
1004                .collect::<Vec<Entity>>()
1005        }
1006
1007        assert_eq!(get_added::<A>(&mut world), vec![e1]);
1008        world.entity_mut(e1).insert(B(0));
1009        assert_eq!(get_added::<A>(&mut world), vec![e1]);
1010        assert_eq!(get_added::<B>(&mut world), vec![e1]);
1011
1012        world.clear_trackers();
1013        assert!(get_added::<A>(&mut world).is_empty());
1014        let e2 = world.spawn((A(1), B(1))).id();
1015        assert_eq!(get_added::<A>(&mut world), vec![e2]);
1016        assert_eq!(get_added::<B>(&mut world), vec![e2]);
1017
1018        let added = world
1019            .query_filtered::<Entity, (Added<A>, Added<B>)>()
1020            .iter(&world)
1021            .collect::<Vec<Entity>>();
1022        assert_eq!(added, vec![e2]);
1023    }
1024
1025    #[test]
1026    fn changed_trackers() {
1027        let mut world = World::default();
1028        let e1 = world.spawn((A(0), B(0))).id();
1029        let e2 = world.spawn((A(0), B(0))).id();
1030        let e3 = world.spawn((A(0), B(0))).id();
1031        world.spawn((A(0), B(0)));
1032
1033        world.clear_trackers();
1034
1035        for (i, mut a) in world.query::<&mut A>().iter_mut(&mut world).enumerate() {
1036            if i % 2 == 0 {
1037                a.0 += 1;
1038            }
1039        }
1040
1041        fn get_filtered<F: QueryFilter>(world: &mut World) -> EntityHashSet {
1042            world
1043                .query_filtered::<Entity, F>()
1044                .iter(world)
1045                .collect::<EntityHashSet>()
1046        }
1047
1048        assert_eq!(
1049            get_filtered::<Changed<A>>(&mut world),
1050            [e1, e3].into_iter().collect::<EntityHashSet>()
1051        );
1052
1053        // ensure changing an entity's archetypes also moves its changed state
1054        world.entity_mut(e1).insert(C);
1055
1056        assert_eq!(
1057            get_filtered::<Changed<A>>(&mut world),
1058            [e3, e1].into_iter().collect::<EntityHashSet>(),
1059            "changed entities list should not change"
1060        );
1061
1062        // spawning a new A entity should not change existing changed state
1063        world.entity_mut(e1).insert((A(0), B(0)));
1064
1065        assert_eq!(
1066            get_filtered::<Changed<A>>(&mut world),
1067            [e3, e1].into_iter().collect::<EntityHashSet>(),
1068            "changed entities list should not change"
1069        );
1070
1071        // removing an unchanged entity should not change changed state
1072        assert!(world.despawn(e2));
1073        assert_eq!(
1074            get_filtered::<Changed<A>>(&mut world),
1075            [e3, e1].into_iter().collect::<EntityHashSet>(),
1076            "changed entities list should not change"
1077        );
1078
1079        // removing a changed entity should remove it from enumeration
1080        assert!(world.despawn(e1));
1081        assert_eq!(
1082            get_filtered::<Changed<A>>(&mut world),
1083            [e3].into_iter().collect::<EntityHashSet>(),
1084            "e1 should no longer be returned"
1085        );
1086
1087        world.clear_trackers();
1088
1089        assert!(get_filtered::<Changed<A>>(&mut world).is_empty());
1090
1091        let e4 = world.spawn_empty().id();
1092
1093        world.entity_mut(e4).insert(A(0));
1094        assert_eq!(
1095            get_filtered::<Changed<A>>(&mut world),
1096            [e4].into_iter().collect::<EntityHashSet>()
1097        );
1098        assert_eq!(
1099            get_filtered::<Added<A>>(&mut world),
1100            [e4].into_iter().collect::<EntityHashSet>()
1101        );
1102
1103        world.entity_mut(e4).insert(A(1));
1104        assert_eq!(
1105            get_filtered::<Changed<A>>(&mut world),
1106            [e4].into_iter().collect::<EntityHashSet>()
1107        );
1108
1109        world.clear_trackers();
1110
1111        // ensure inserting multiple components set changed state for all components and set added
1112        // state for non existing components even when changing archetype.
1113        world.entity_mut(e4).insert((A(0), B(0)));
1114
1115        assert!(get_filtered::<Added<A>>(&mut world).is_empty());
1116        assert_eq!(
1117            get_filtered::<Changed<A>>(&mut world),
1118            [e4].into_iter().collect::<EntityHashSet>()
1119        );
1120        assert_eq!(
1121            get_filtered::<Added<B>>(&mut world),
1122            [e4].into_iter().collect::<EntityHashSet>()
1123        );
1124        assert_eq!(
1125            get_filtered::<Changed<B>>(&mut world),
1126            [e4].into_iter().collect::<EntityHashSet>()
1127        );
1128    }
1129
1130    #[test]
1131    fn changed_trackers_sparse() {
1132        let mut world = World::default();
1133        let e1 = world.spawn(SparseStored(0)).id();
1134        let e2 = world.spawn(SparseStored(0)).id();
1135        let e3 = world.spawn(SparseStored(0)).id();
1136        world.spawn(SparseStored(0));
1137
1138        world.clear_trackers();
1139
1140        for (i, mut a) in world
1141            .query::<&mut SparseStored>()
1142            .iter_mut(&mut world)
1143            .enumerate()
1144        {
1145            if i % 2 == 0 {
1146                a.0 += 1;
1147            }
1148        }
1149
1150        fn get_filtered<F: QueryFilter>(world: &mut World) -> EntityHashSet {
1151            world
1152                .query_filtered::<Entity, F>()
1153                .iter(world)
1154                .collect::<EntityHashSet>()
1155        }
1156
1157        assert_eq!(
1158            get_filtered::<Changed<SparseStored>>(&mut world),
1159            [e1, e3].into_iter().collect::<EntityHashSet>()
1160        );
1161
1162        // ensure changing an entity's archetypes also moves its changed state
1163        world.entity_mut(e1).insert(C);
1164
1165        assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), [e3, e1].into_iter().collect::<EntityHashSet>(), "changed entities list should not change (although the order will due to archetype moves)");
1166
1167        // spawning a new SparseStored entity should not change existing changed state
1168        world.entity_mut(e1).insert(SparseStored(0));
1169        assert_eq!(
1170            get_filtered::<Changed<SparseStored>>(&mut world),
1171            [e3, e1].into_iter().collect::<EntityHashSet>(),
1172            "changed entities list should not change"
1173        );
1174
1175        // removing an unchanged entity should not change changed state
1176        assert!(world.despawn(e2));
1177        assert_eq!(
1178            get_filtered::<Changed<SparseStored>>(&mut world),
1179            [e3, e1].into_iter().collect::<EntityHashSet>(),
1180            "changed entities list should not change"
1181        );
1182
1183        // removing a changed entity should remove it from enumeration
1184        assert!(world.despawn(e1));
1185        assert_eq!(
1186            get_filtered::<Changed<SparseStored>>(&mut world),
1187            [e3].into_iter().collect::<EntityHashSet>(),
1188            "e1 should no longer be returned"
1189        );
1190
1191        world.clear_trackers();
1192
1193        assert!(get_filtered::<Changed<SparseStored>>(&mut world).is_empty());
1194
1195        let e4 = world.spawn_empty().id();
1196
1197        world.entity_mut(e4).insert(SparseStored(0));
1198        assert_eq!(
1199            get_filtered::<Changed<SparseStored>>(&mut world),
1200            [e4].into_iter().collect::<EntityHashSet>()
1201        );
1202        assert_eq!(
1203            get_filtered::<Added<SparseStored>>(&mut world),
1204            [e4].into_iter().collect::<EntityHashSet>()
1205        );
1206
1207        world.entity_mut(e4).insert(A(1));
1208        assert_eq!(
1209            get_filtered::<Changed<SparseStored>>(&mut world),
1210            [e4].into_iter().collect::<EntityHashSet>()
1211        );
1212
1213        world.clear_trackers();
1214
1215        // ensure inserting multiple components set changed state for all components and set added
1216        // state for non existing components even when changing archetype.
1217        world.entity_mut(e4).insert(SparseStored(0));
1218
1219        assert!(get_filtered::<Added<SparseStored>>(&mut world).is_empty());
1220        assert_eq!(
1221            get_filtered::<Changed<SparseStored>>(&mut world),
1222            [e4].into_iter().collect::<EntityHashSet>()
1223        );
1224    }
1225
1226    #[test]
1227    fn empty_spawn() {
1228        let mut world = World::default();
1229        let e = world.spawn_empty().id();
1230        let mut e_mut = world.entity_mut(e);
1231        e_mut.insert(A(0));
1232        assert_eq!(e_mut.get::<A>().unwrap(), &A(0));
1233    }
1234
1235    #[test]
1236    fn changed_query() {
1237        let mut world = World::default();
1238        let e1 = world.spawn((A(0), B(0))).id();
1239
1240        fn get_changed(world: &mut World) -> Vec<Entity> {
1241            world
1242                .query_filtered::<Entity, Changed<A>>()
1243                .iter(world)
1244                .collect::<Vec<Entity>>()
1245        }
1246        assert_eq!(get_changed(&mut world), vec![e1]);
1247        world.clear_trackers();
1248        assert_eq!(get_changed(&mut world), vec![]);
1249        *world.get_mut(e1).unwrap() = A(1);
1250        assert_eq!(get_changed(&mut world), vec![e1]);
1251    }
1252
1253    #[test]
1254    fn resource() {
1255        use crate::resource::Resource;
1256
1257        #[derive(Resource, PartialEq, Debug)]
1258        struct Num(i32);
1259
1260        #[derive(Resource, PartialEq, Debug)]
1261        struct BigNum(u64);
1262        let mut world = World::default();
1263        assert!(world.get_resource::<Num>().is_none());
1264        assert!(!world.contains_resource::<Num>());
1265        assert!(!world.is_resource_added::<Num>());
1266        assert!(!world.is_resource_changed::<Num>());
1267
1268        world.insert_resource(Num(123));
1269        let resource_id = world.components().get_id(TypeId::of::<Num>()).unwrap();
1270
1271        assert_eq!(world.resource::<Num>().0, 123);
1272        assert!(world.contains_resource::<Num>());
1273        assert!(world.is_resource_added::<Num>());
1274        assert!(world.is_resource_changed::<Num>());
1275
1276        world.insert_resource(BigNum(456));
1277        assert_eq!(world.resource::<BigNum>().0, 456u64);
1278
1279        world.insert_resource(BigNum(789));
1280        assert_eq!(world.resource::<BigNum>().0, 789);
1281
1282        {
1283            let mut value = world.resource_mut::<BigNum>();
1284            assert_eq!(value.0, 789);
1285            value.0 = 10;
1286        }
1287
1288        assert_eq!(
1289            world.resource::<BigNum>().0,
1290            10,
1291            "resource changes are preserved"
1292        );
1293
1294        assert_eq!(
1295            world.remove_resource::<BigNum>(),
1296            Some(BigNum(10)),
1297            "removed resource has the correct value"
1298        );
1299        assert_eq!(
1300            world.get_resource::<BigNum>(),
1301            None,
1302            "removed resource no longer exists"
1303        );
1304        assert_eq!(
1305            world.remove_resource::<BigNum>(),
1306            None,
1307            "double remove returns nothing"
1308        );
1309
1310        world.insert_resource(BigNum(1));
1311        assert_eq!(
1312            world.get_resource::<BigNum>(),
1313            Some(&BigNum(1)),
1314            "re-inserting resources works"
1315        );
1316
1317        assert_eq!(
1318            world.get_resource::<Num>(),
1319            Some(&Num(123)),
1320            "other resources are unaffected"
1321        );
1322
1323        let current_resource_id = world.components().get_id(TypeId::of::<Num>()).unwrap();
1324        assert_eq!(
1325            resource_id, current_resource_id,
1326            "resource id does not change after removing / re-adding"
1327        );
1328    }
1329
1330    #[test]
1331    fn remove() {
1332        let mut world = World::default();
1333        let e1 = world.spawn((A(1), B(1), TableStored("a"))).id();
1334
1335        let mut e = world.entity_mut(e1);
1336        assert_eq!(e.get::<TableStored>(), Some(&TableStored("a")));
1337        assert_eq!(e.get::<A>(), Some(&A(1)));
1338        assert_eq!(e.get::<B>(), Some(&B(1)));
1339        assert_eq!(
1340            e.get::<C>(),
1341            None,
1342            "C is not in the entity, so it should not exist"
1343        );
1344
1345        e.remove::<(A, B, C)>();
1346        assert_eq!(
1347            e.get::<TableStored>(),
1348            Some(&TableStored("a")),
1349            "TableStored is not in the removed bundle, so it should exist"
1350        );
1351        assert_eq!(
1352            e.get::<A>(),
1353            None,
1354            "Num is in the removed bundle, so it should not exist"
1355        );
1356        assert_eq!(
1357            e.get::<B>(),
1358            None,
1359            "f64 is in the removed bundle, so it should not exist"
1360        );
1361        assert_eq!(
1362            e.get::<C>(),
1363            None,
1364            "usize is in the removed bundle, so it should not exist"
1365        );
1366    }
1367
1368    #[test]
1369    fn take() {
1370        let mut world = World::default();
1371        world.spawn((A(1), B(1), TableStored("1")));
1372        let e2 = world.spawn((A(2), B(2), TableStored("2"))).id();
1373        world.spawn((A(3), B(3), TableStored("3")));
1374
1375        let mut query = world.query::<(&B, &TableStored)>();
1376        let results = query
1377            .iter(&world)
1378            .map(|(a, b)| (a.0, b.0))
1379            .collect::<HashSet<_>>();
1380        assert_eq!(
1381            results,
1382            [(1, "1"), (2, "2"), (3, "3"),]
1383                .into_iter()
1384                .collect::<HashSet<_>>()
1385        );
1386
1387        let removed_bundle = world.entity_mut(e2).take::<(B, TableStored)>().unwrap();
1388        assert_eq!(removed_bundle, (B(2), TableStored("2")));
1389
1390        let results = query
1391            .iter(&world)
1392            .map(|(a, b)| (a.0, b.0))
1393            .collect::<HashSet<_>>();
1394        assert_eq!(
1395            results,
1396            [(1, "1"), (3, "3"),].into_iter().collect::<HashSet<_>>()
1397        );
1398
1399        let mut a_query = world.query::<&A>();
1400        let results = a_query.iter(&world).map(|a| a.0).collect::<HashSet<_>>();
1401        assert_eq!(results, [1, 3, 2].into_iter().collect::<HashSet<_>>());
1402
1403        let entity_ref = world.entity(e2);
1404        assert_eq!(
1405            entity_ref.get::<A>(),
1406            Some(&A(2)),
1407            "A is not in the removed bundle, so it should exist"
1408        );
1409        assert_eq!(
1410            entity_ref.get::<B>(),
1411            None,
1412            "B is in the removed bundle, so it should not exist"
1413        );
1414        assert_eq!(
1415            entity_ref.get::<TableStored>(),
1416            None,
1417            "TableStored is in the removed bundle, so it should not exist"
1418        );
1419    }
1420
1421    #[test]
1422    fn non_send() {
1423        let mut world = World::default();
1424        world.insert_non_send(123i32);
1425        world.insert_non_send(456i64);
1426        assert_eq!(*world.non_send::<i32>(), 123);
1427        assert_eq!(*world.non_send_mut::<i64>(), 456);
1428    }
1429
1430    #[test]
1431    fn non_send_points_to_distinct_data() {
1432        let mut world = World::default();
1433        world.insert_resource(ResA(123));
1434        world.insert_non_send(ResA(456));
1435        assert_eq!(*world.resource::<ResA>(), ResA(123));
1436        assert_eq!(*world.non_send::<ResA>(), ResA(456));
1437    }
1438
1439    #[test]
1440    #[should_panic]
1441    fn non_send_panic() {
1442        let mut world = World::default();
1443        world.insert_non_send(0i32);
1444        std::thread::spawn(move || {
1445            let _ = world.non_send_mut::<i32>();
1446        })
1447        .join()
1448        .unwrap();
1449    }
1450
1451    #[test]
1452    fn exact_size_query() {
1453        let mut world = World::default();
1454        world.spawn((A(0), B(0)));
1455        world.spawn((A(0), B(0)));
1456        world.spawn((A(0), B(0), C));
1457        world.spawn(C);
1458
1459        let mut query = world.query::<(&A, &B)>();
1460        assert_eq!(query.iter(&world).len(), 3);
1461    }
1462
1463    #[test]
1464    #[should_panic]
1465    fn duplicate_components_panic() {
1466        let mut world = World::new();
1467        world.spawn((A(1), A(2)));
1468    }
1469
1470    #[test]
1471    #[should_panic]
1472    fn ref_and_mut_query_panic() {
1473        let mut world = World::new();
1474        world.query::<(&A, &mut A)>();
1475    }
1476
1477    #[test]
1478    #[should_panic]
1479    fn entity_ref_and_mut_query_panic() {
1480        let mut world = World::new();
1481        world.query::<(EntityRef, &mut A)>();
1482    }
1483
1484    #[test]
1485    #[should_panic]
1486    fn mut_and_ref_query_panic() {
1487        let mut world = World::new();
1488        world.query::<(&mut A, &A)>();
1489    }
1490
1491    #[test]
1492    #[should_panic]
1493    fn mut_and_entity_ref_query_panic() {
1494        let mut world = World::new();
1495        world.query::<(&mut A, EntityRef)>();
1496    }
1497
1498    #[test]
1499    #[should_panic]
1500    fn entity_ref_and_entity_mut_query_panic() {
1501        let mut world = World::new();
1502        world.query::<(EntityRef, EntityMut)>();
1503    }
1504
1505    #[test]
1506    #[should_panic]
1507    fn entity_mut_and_entity_mut_query_panic() {
1508        let mut world = World::new();
1509        world.query::<(EntityMut, EntityMut)>();
1510    }
1511
1512    #[test]
1513    fn entity_ref_and_entity_ref_query_no_panic() {
1514        let mut world = World::new();
1515        world.query::<(EntityRef, EntityRef)>();
1516    }
1517
1518    #[test]
1519    #[should_panic]
1520    fn mut_and_mut_query_panic() {
1521        let mut world = World::new();
1522        world.query::<(&mut A, &mut A)>();
1523    }
1524
1525    #[test]
1526    #[should_panic]
1527    fn multiple_worlds_same_query_iter() {
1528        let mut world_a = World::new();
1529        let world_b = World::new();
1530        let mut query = world_a.query::<&A>();
1531        query.iter(&world_a);
1532        query.iter(&world_b);
1533    }
1534
1535    #[test]
1536    fn query_filters_dont_collide_with_fetches() {
1537        let mut world = World::new();
1538        world.query_filtered::<&mut A, Changed<A>>();
1539    }
1540
1541    #[test]
1542    fn filtered_query_access() {
1543        let mut world = World::new();
1544        // We remove entity disabling so it doesn't affect our query filters
1545        world.remove_resource::<DefaultQueryFilters>();
1546        let query = world.query_filtered::<&mut A, Changed<B>>();
1547
1548        let mut expected = FilteredAccess::default();
1549        let a_id = world.components.get_id(TypeId::of::<A>()).unwrap();
1550        let b_id = world.components.get_id(TypeId::of::<B>()).unwrap();
1551        expected.add_write(a_id);
1552        expected.add_read(b_id);
1553        assert!(
1554            query.component_access.eq(&expected),
1555            "ComponentId access from query fetch and query filter should be combined"
1556        );
1557    }
1558
1559    #[test]
1560    #[should_panic]
1561    fn multiple_worlds_same_query_get() {
1562        let mut world_a = World::new();
1563        let world_b = World::new();
1564        let mut query = world_a.query::<&A>();
1565        let _ = query.get(&world_a, Entity::from_raw_u32(10_000).unwrap());
1566        let _ = query.get(&world_b, Entity::from_raw_u32(10_000).unwrap());
1567    }
1568
1569    #[test]
1570    #[should_panic]
1571    fn multiple_worlds_same_query_for_each() {
1572        let mut world_a = World::new();
1573        let world_b = World::new();
1574        let mut query = world_a.query::<&A>();
1575        query.iter(&world_a).for_each(|_| {});
1576        query.iter(&world_b).for_each(|_| {});
1577    }
1578
1579    #[test]
1580    fn resource_scope() {
1581        let mut world = World::default();
1582        assert!(world.try_resource_scope::<ResA, _>(|_, _| {}).is_none());
1583        world.insert_resource(ResA(0));
1584        world.resource_scope(|world: &mut World, mut value: Mut<ResA>| {
1585            value.0 += 1;
1586            assert!(!world.contains_resource::<ResA>());
1587        });
1588        assert_eq!(world.resource::<ResA>().0, 1);
1589    }
1590
1591    #[cfg(feature = "std")]
1592    #[test]
1593    fn resource_scope_unwind() {
1594        #[derive(Debug, PartialEq)]
1595        struct Panic;
1596
1597        let mut world = World::default();
1598        assert!(world.try_resource_scope::<ResA, _>(|_, _| {}).is_none());
1599        world.insert_resource(ResA(0));
1600        let panic = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
1601            world.resource_scope(|world: &mut World, _value: Mut<ResA>| {
1602                assert!(!world.contains_resource::<ResA>());
1603                std::panic::panic_any(Panic);
1604            });
1605            unreachable!();
1606        }));
1607        assert_eq!(panic.unwrap_err().downcast_ref::<Panic>(), Some(&Panic));
1608        assert!(world.contains_resource::<ResA>());
1609    }
1610
1611    #[test]
1612    fn resource_scope_resources_cleared() {
1613        let mut world = World::default();
1614        assert!(world.try_resource_scope::<ResA, _>(|_, _| {}).is_none());
1615        world.insert_resource(ResA(0));
1616        let r = world.try_resource_scope(|world: &mut World, _value: Mut<ResA>| {
1617            assert!(!world.contains_resource::<ResA>());
1618            world.clear_resources();
1619        });
1620        assert_eq!(r, Some(()));
1621        assert!(world.contains_resource::<ResA>());
1622    }
1623
1624    #[test]
1625    #[should_panic]
1626    fn non_send_drop_from_different_thread() {
1627        let mut world = World::default();
1628        world.insert_non_send(NonSendA::default());
1629
1630        let thread = std::thread::spawn(move || {
1631            // Dropping the non-send resource on a different thread
1632            // Should result in a panic
1633            drop(world);
1634        });
1635
1636        if let Err(err) = thread.join() {
1637            std::panic::resume_unwind(err);
1638        }
1639    }
1640
1641    #[test]
1642    fn non_send_drop_from_same_thread() {
1643        let mut world = World::default();
1644        world.insert_non_send(NonSendA::default());
1645        drop(world);
1646    }
1647
1648    #[test]
1649    fn insert_overwrite_drop() {
1650        let (dropck1, dropped1) = DropCk::new_pair();
1651        let (dropck2, dropped2) = DropCk::new_pair();
1652        let mut world = World::default();
1653        world.spawn(dropck1).insert(dropck2);
1654        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1655        assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1656        drop(world);
1657        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1658        assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1659    }
1660
1661    #[test]
1662    fn insert_overwrite_drop_sparse() {
1663        let (dropck1, dropped1) = DropCk::new_pair();
1664        let (dropck2, dropped2) = DropCk::new_pair();
1665        let mut world = World::default();
1666
1667        world
1668            .spawn(DropCkSparse(dropck1))
1669            .insert(DropCkSparse(dropck2));
1670        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1671        assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1672        drop(world);
1673        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1674        assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1675    }
1676
1677    #[test]
1678    fn clear_entities() {
1679        let mut world = World::default();
1680
1681        world.insert_resource(ResA(0));
1682        world.spawn(A(1));
1683        world.spawn(SparseStored(1));
1684
1685        let mut q1 = world.query::<&A>();
1686        let mut q2 = world.query::<&SparseStored>();
1687
1688        assert_eq!(q1.query(&world).count(), 1);
1689        assert_eq!(q2.query(&world).count(), 1);
1690
1691        world.clear_entities();
1692
1693        assert_eq!(
1694            q1.query(&world).count(),
1695            0,
1696            "world should not contain table components"
1697        );
1698        assert_eq!(
1699            q2.query(&world).count(),
1700            0,
1701            "world should not contain sparse set components"
1702        );
1703        assert_eq!(
1704            world.get_resource::<ResA>(),
1705            None,
1706            "world should not contain resources"
1707        );
1708    }
1709
1710    #[test]
1711    fn test_is_archetypal_size_hints() {
1712        let mut world = World::default();
1713        macro_rules! query_min_size {
1714            ($query:ty, $filter:ty) => {
1715                world
1716                    .query_filtered::<$query, $filter>()
1717                    .iter(&world)
1718                    .size_hint()
1719                    .0
1720            };
1721        }
1722
1723        world.spawn((A(1), B(1), C));
1724        world.spawn((A(1), C));
1725        world.spawn((A(1), B(1)));
1726        world.spawn((B(1), C));
1727        world.spawn(A(1));
1728        world.spawn(C);
1729        assert_eq!(2, query_min_size![(), (With<A>, Without<B>)]);
1730        assert_eq!(3, query_min_size![&B, Or<(With<A>, With<C>)>]);
1731        assert_eq!(1, query_min_size![&B, (With<A>, With<C>)]);
1732        assert_eq!(1, query_min_size![(&A, &B), With<C>]);
1733        assert_eq!(4, query_min_size![&A, ()], "Simple Archetypal");
1734        assert_eq!(4, query_min_size![Ref<A>, ()]);
1735        // All the following should set minimum size to 0, as it's impossible to predict
1736        // how many entities the filters will trim.
1737        assert_eq!(0, query_min_size![(), Added<A>], "Simple Added");
1738        assert_eq!(0, query_min_size![(), Changed<A>], "Simple Changed");
1739        assert_eq!(0, query_min_size![(&A, &B), Changed<A>]);
1740        assert_eq!(0, query_min_size![&A, (Changed<A>, With<B>)]);
1741        assert_eq!(0, query_min_size![(&A, &B), Or<(Changed<A>, Changed<B>)>]);
1742    }
1743
1744    #[test]
1745    fn insert_batch() {
1746        let mut world = World::default();
1747        let e0 = world.spawn(A(0)).id();
1748        let e1 = world.spawn(B(0)).id();
1749
1750        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1751
1752        world.insert_batch(values);
1753
1754        assert_eq!(
1755            world.get::<A>(e0),
1756            Some(&A(1)),
1757            "first entity's A component should have been replaced"
1758        );
1759        assert_eq!(
1760            world.get::<B>(e0),
1761            Some(&B(0)),
1762            "first entity should have received B component"
1763        );
1764        assert_eq!(
1765            world.get::<A>(e1),
1766            Some(&A(0)),
1767            "second entity should have received A component"
1768        );
1769        assert_eq!(
1770            world.get::<B>(e1),
1771            Some(&B(1)),
1772            "second entity's B component should have been replaced"
1773        );
1774    }
1775
1776    #[test]
1777    fn insert_batch_same_archetype() {
1778        let mut world = World::default();
1779        let e0 = world.spawn((A(0), B(0))).id();
1780        let e1 = world.spawn((A(0), B(0))).id();
1781        let e2 = world.spawn(B(0)).id();
1782
1783        let values = vec![(e0, (B(1), C)), (e1, (B(2), C)), (e2, (B(3), C))];
1784
1785        world.insert_batch(values);
1786        let mut query = world.query::<(Option<&A>, &B, &C)>();
1787        let component_values = query.get_many(&world, [e0, e1, e2]).unwrap();
1788
1789        assert_eq!(
1790            component_values,
1791            [(Some(&A(0)), &B(1), &C), (Some(&A(0)), &B(2), &C), (None, &B(3), &C)],
1792            "all entities should have had their B component replaced, received C component, and had their A component (or lack thereof) unchanged"
1793        );
1794    }
1795
1796    #[test]
1797    fn insert_batch_if_new() {
1798        let mut world = World::default();
1799        let e0 = world.spawn(A(0)).id();
1800        let e1 = world.spawn(B(0)).id();
1801
1802        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1803
1804        world.insert_batch_if_new(values);
1805
1806        assert_eq!(
1807            world.get::<A>(e0),
1808            Some(&A(0)),
1809            "first entity's A component should not have been replaced"
1810        );
1811        assert_eq!(
1812            world.get::<B>(e0),
1813            Some(&B(0)),
1814            "first entity should have received B component"
1815        );
1816        assert_eq!(
1817            world.get::<A>(e1),
1818            Some(&A(0)),
1819            "second entity should have received A component"
1820        );
1821        assert_eq!(
1822            world.get::<B>(e1),
1823            Some(&B(0)),
1824            "second entity's B component should not have been replaced"
1825        );
1826    }
1827
1828    #[test]
1829    fn try_insert_batch() {
1830        let mut world = World::default();
1831        let e0 = world.spawn(A(0)).id();
1832        let e1 = Entity::from_raw_u32(10_000).unwrap();
1833
1834        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1835
1836        let error = world.try_insert_batch(values).unwrap_err();
1837
1838        assert_eq!(e1, error.entities[0]);
1839
1840        assert_eq!(
1841            world.get::<A>(e0),
1842            Some(&A(1)),
1843            "first entity's A component should have been replaced"
1844        );
1845        assert_eq!(
1846            world.get::<B>(e0),
1847            Some(&B(0)),
1848            "first entity should have received B component"
1849        );
1850    }
1851
1852    #[test]
1853    fn try_insert_batch_if_new() {
1854        let mut world = World::default();
1855        let e0 = world.spawn(A(0)).id();
1856        let e1 = Entity::from_raw_u32(10_000).unwrap();
1857
1858        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1859
1860        let error = world.try_insert_batch_if_new(values).unwrap_err();
1861
1862        assert_eq!(e1, error.entities[0]);
1863
1864        assert_eq!(
1865            world.get::<A>(e0),
1866            Some(&A(0)),
1867            "first entity's A component should not have been replaced"
1868        );
1869        assert_eq!(
1870            world.get::<B>(e0),
1871            Some(&B(0)),
1872            "first entity should have received B component"
1873        );
1874    }
1875
1876    #[derive(Default)]
1877    struct CaptureMapper(Vec<Entity>);
1878    impl EntityMapper for CaptureMapper {
1879        fn get_mapped(&mut self, source: Entity) -> Entity {
1880            self.0.push(source);
1881            source
1882        }
1883
1884        fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
1885    }
1886
1887    #[test]
1888    fn map_struct_entities() {
1889        #[derive(Component)]
1890        #[expect(
1891            unused,
1892            reason = "extra fields are used to ensure the derive works properly"
1893        )]
1894        struct Foo(usize, #[entities] Entity);
1895
1896        #[derive(Component)]
1897        #[expect(
1898            unused,
1899            reason = "extra fields are used to ensure the derive works properly"
1900        )]
1901        struct Bar {
1902            #[entities]
1903            a: Entity,
1904            b: usize,
1905            #[entities]
1906            c: Vec<Entity>,
1907        }
1908
1909        let mut world = World::new();
1910        let e1 = world.spawn_empty().id();
1911        let e2 = world.spawn_empty().id();
1912        let e3 = world.spawn_empty().id();
1913
1914        let mut foo = Foo(1, e1);
1915        let mut mapper = CaptureMapper::default();
1916        Component::map_entities(&mut foo, &mut mapper);
1917        assert_eq!(&mapper.0, &[e1]);
1918
1919        let mut bar = Bar {
1920            a: e1,
1921            b: 1,
1922            c: vec![e2, e3],
1923        };
1924        let mut mapper = CaptureMapper::default();
1925        Component::map_entities(&mut bar, &mut mapper);
1926        assert_eq!(&mapper.0, &[e1, e2, e3]);
1927    }
1928
1929    #[test]
1930    fn map_enum_entities() {
1931        #[derive(Component)]
1932        #[expect(
1933            unused,
1934            reason = "extra fields are used to ensure the derive works properly"
1935        )]
1936        enum Foo {
1937            Bar(usize, #[entities] Entity),
1938            Baz {
1939                #[entities]
1940                a: Entity,
1941                b: usize,
1942                #[entities]
1943                c: Vec<Entity>,
1944            },
1945        }
1946
1947        let mut world = World::new();
1948        let e1 = world.spawn_empty().id();
1949        let e2 = world.spawn_empty().id();
1950        let e3 = world.spawn_empty().id();
1951
1952        let mut foo = Foo::Bar(1, e1);
1953        let mut mapper = CaptureMapper::default();
1954        Component::map_entities(&mut foo, &mut mapper);
1955        assert_eq!(&mapper.0, &[e1]);
1956
1957        let mut foo = Foo::Baz {
1958            a: e1,
1959            b: 1,
1960            c: vec![e2, e3],
1961        };
1962        let mut mapper = CaptureMapper::default();
1963        Component::map_entities(&mut foo, &mut mapper);
1964        assert_eq!(&mapper.0, &[e1, e2, e3]);
1965    }
1966
1967    #[expect(
1968        dead_code,
1969        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1970    )]
1971    #[derive(Component)]
1972    struct ComponentA(u32);
1973
1974    #[expect(
1975        dead_code,
1976        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1977    )]
1978    #[derive(Component)]
1979    struct ComponentB(u32);
1980
1981    #[derive(Bundle)]
1982    struct Simple(ComponentA);
1983
1984    #[expect(
1985        dead_code,
1986        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1987    )]
1988    #[derive(Bundle)]
1989    struct Tuple(Simple, ComponentB);
1990
1991    #[expect(
1992        dead_code,
1993        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1994    )]
1995    #[derive(Bundle)]
1996    struct Record {
1997        field0: Simple,
1998        field1: ComponentB,
1999    }
2000
2001    #[expect(
2002        dead_code,
2003        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
2004    )]
2005    #[derive(Component)]
2006    struct MyEntities {
2007        #[entities]
2008        entities: Vec<Entity>,
2009        #[entities]
2010        another_one: Entity,
2011        #[entities]
2012        maybe_entity: Option<Entity>,
2013        something_else: String,
2014    }
2015
2016    #[expect(
2017        dead_code,
2018        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
2019    )]
2020    #[derive(Component)]
2021    struct MyEntitiesTuple(#[entities] Vec<Entity>, #[entities] Entity, usize);
2022
2023    #[test]
2024    fn clone_entities() {
2025        use crate::entity::{ComponentCloneCtx, SourceComponent};
2026
2027        #[expect(
2028            dead_code,
2029            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2030        )]
2031        #[derive(Component)]
2032        #[component(clone_behavior = Ignore)]
2033        struct IgnoreClone;
2034
2035        #[expect(
2036            dead_code,
2037            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2038        )]
2039        #[derive(Component)]
2040        #[component(clone_behavior = Default)]
2041        struct DefaultClone;
2042
2043        #[expect(
2044            dead_code,
2045            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2046        )]
2047        #[derive(Component)]
2048        #[component(clone_behavior = Custom(custom_clone))]
2049        struct CustomClone;
2050
2051        #[expect(
2052            dead_code,
2053            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2054        )]
2055        #[derive(Component, Clone)]
2056        #[component(clone_behavior = clone::<Self>())]
2057        struct CloneFunction;
2058
2059        #[expect(
2060            dead_code,
2061            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2062        )]
2063        fn custom_clone(_source: &SourceComponent, _ctx: &mut ComponentCloneCtx) {}
2064    }
2065
2066    #[test]
2067    #[cfg_attr(miri, ignore = "This test takes ~460s on CI")]
2068    fn queue_register_component_toctou() {
2069        for _ in 0..1000 {
2070            let w = World::new();
2071
2072            std::thread::scope(|s| {
2073                let c1 = s.spawn(|| w.components_queue().queue_register_component::<A>());
2074                let c2 = s.spawn(|| w.components_queue().queue_register_component::<A>());
2075                assert_eq!(c1.join().unwrap(), c2.join().unwrap());
2076            });
2077        }
2078    }
2079}