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