bevy_ecs/world/unsafe_world_cell.rs
1//! Contains types that allow disjoint mutable access to a [`World`].
2
3use super::{Mut, Ref, World, WorldId};
4use crate::{
5 archetype::{Archetype, Archetypes},
6 bundle::Bundles,
7 change_detection::{
8 ComponentTickCells, ComponentTicks, ComponentTicksMut, ComponentTicksRef, MaybeLocation,
9 MutUntyped, Tick,
10 },
11 component::{ComponentId, Components, Mutable, StorageType},
12 entity::{
13 ContainsEntity, Entities, Entity, EntityAllocator, EntityLocation, EntityNotSpawnedError,
14 },
15 error::{DefaultErrorHandler, ErrorHandler},
16 lifecycle::RemovedComponentMessages,
17 observer::Observers,
18 prelude::Component,
19 query::{DebugCheckedUnwrap, QueryAccessError, ReleaseStateQueryData},
20 resource::Resource,
21 storage::{ComponentSparseSet, Storages, Table},
22 world::RawCommandQueue,
23};
24use bevy_platform::sync::atomic::Ordering;
25use bevy_ptr::Ptr;
26use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr};
27use thiserror::Error;
28
29/// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid
30/// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.
31///
32/// ### Rationale
33/// In rust, having a `&mut World` means that there are absolutely no other references to the safe world alive at the same time,
34/// without exceptions. Not even unsafe code can change this.
35///
36/// But there are situations where careful shared mutable access through a type is possible and safe. For this, rust provides the [`UnsafeCell`]
37/// escape hatch, which allows you to get a `*mut T` from a `&UnsafeCell<T>` and around which safe abstractions can be built.
38///
39/// Access to resources and components can be done uniquely using [`World::resource_mut`] and [`World::entity_mut`], and shared using [`World::resource`] and [`World::entity`].
40/// These methods use lifetimes to check at compile time that no aliasing rules are being broken.
41///
42/// This alone is not enough to implement bevy systems where multiple systems can access *disjoint* parts of the world concurrently. For this, bevy stores all values of
43/// resources and components (and [`ComponentTicks`]) in [`UnsafeCell`]s, and carefully validates disjoint access patterns using
44/// APIs like [`System::initialize`](crate::system::System::initialize).
45///
46/// A system then can be executed using [`System::run_unsafe`](crate::system::System::run_unsafe) with a `&World` and use methods with interior mutability to access resource values.
47///
48/// ### Example Usage
49///
50/// [`UnsafeWorldCell`] can be used as a building block for writing APIs that safely allow disjoint access into the world.
51/// In the following example, the world is split into a resource access half and a component access half, where each one can
52/// safely hand out mutable references.
53///
54/// ```
55/// use bevy_ecs::world::World;
56/// use bevy_ecs::change_detection::Mut;
57/// use bevy_ecs::resource::Resource;
58/// use bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell;
59///
60/// // INVARIANT: existence of this struct means that users of it are the only ones being able to access resources in the world
61/// struct OnlyResourceAccessWorld<'w>(UnsafeWorldCell<'w>);
62/// // INVARIANT: existence of this struct means that users of it are the only ones being able to access components in the world
63/// struct OnlyComponentAccessWorld<'w>(UnsafeWorldCell<'w>);
64///
65/// impl<'w> OnlyResourceAccessWorld<'w> {
66/// fn get_resource_mut<T: Resource>(&mut self) -> Option<Mut<'_, T>> {
67/// // SAFETY: resource access is allowed through this UnsafeWorldCell
68/// unsafe { self.0.get_resource_mut::<T>() }
69/// }
70/// }
71/// // impl<'w> OnlyComponentAccessWorld<'w> {
72/// // ...
73/// // }
74///
75/// // the two `UnsafeWorldCell`s borrow from the `&mut World`, so it cannot be accessed while they are live
76/// fn split_world_access(world: &mut World) -> (OnlyResourceAccessWorld<'_>, OnlyComponentAccessWorld<'_>) {
77/// let unsafe_world_cell = world.as_unsafe_world_cell();
78/// let resource_access = OnlyResourceAccessWorld(unsafe_world_cell);
79/// let component_access = OnlyComponentAccessWorld(unsafe_world_cell);
80/// (resource_access, component_access)
81/// }
82/// ```
83#[derive(Copy, Clone)]
84pub struct UnsafeWorldCell<'w> {
85 ptr: *mut World,
86 #[cfg(debug_assertions)]
87 allows_mutable_access: bool,
88 _marker: PhantomData<(&'w World, &'w UnsafeCell<World>)>,
89}
90
91// SAFETY: `&World` and `&mut World` are both `Send`
92unsafe impl Send for UnsafeWorldCell<'_> {}
93// SAFETY: `&World` and `&mut World` are both `Sync`
94unsafe impl Sync for UnsafeWorldCell<'_> {}
95
96impl<'w> From<&'w mut World> for UnsafeWorldCell<'w> {
97 fn from(value: &'w mut World) -> Self {
98 value.as_unsafe_world_cell()
99 }
100}
101
102impl<'w> From<&'w World> for UnsafeWorldCell<'w> {
103 fn from(value: &'w World) -> Self {
104 value.as_unsafe_world_cell_readonly()
105 }
106}
107
108impl<'w> UnsafeWorldCell<'w> {
109 /// Creates a [`UnsafeWorldCell`] that can be used to access everything immutably
110 #[inline]
111 pub(crate) fn new_readonly(world: &'w World) -> Self {
112 Self {
113 ptr: ptr::from_ref(world).cast_mut(),
114 #[cfg(debug_assertions)]
115 allows_mutable_access: false,
116 _marker: PhantomData,
117 }
118 }
119
120 /// Creates [`UnsafeWorldCell`] that can be used to access everything mutably
121 #[inline]
122 pub(crate) fn new_mutable(world: &'w mut World) -> Self {
123 Self {
124 ptr: ptr::from_mut(world),
125 #[cfg(debug_assertions)]
126 allows_mutable_access: true,
127 _marker: PhantomData,
128 }
129 }
130
131 #[cfg_attr(debug_assertions, inline(never), track_caller)]
132 #[cfg_attr(not(debug_assertions), inline(always))]
133 pub(crate) fn assert_allows_mutable_access(self) {
134 // This annotation is needed because the
135 // allows_mutable_access field doesn't exist otherwise.
136 // Kinda weird, since debug_assert would never be called,
137 // but CI complained in https://github.com/bevyengine/bevy/pull/17393
138 #[cfg(debug_assertions)]
139 debug_assert!(
140 self.allows_mutable_access,
141 "mutating world data via `World::as_unsafe_world_cell_readonly` is forbidden"
142 );
143 }
144
145 /// Gets a mutable reference to the [`World`] this [`UnsafeWorldCell`] belongs to.
146 /// This is an incredibly error-prone operation and is only valid in a small number of circumstances.
147 ///
148 /// Calling this method implies mutable access to the *whole* world (see first point on safety section
149 /// below), which includes all entities, components, and resources. Notably, calling this on
150 /// [`WorldQuery::init_fetch`](crate::query::WorldQuery::init_fetch) and
151 /// [`SystemParam::get_param`](crate::system::SystemParam::get_param) are most likely *unsound* unless
152 /// you can prove that the underlying [`World`] is exclusive, which in normal circumstances is not.
153 ///
154 /// # Safety
155 /// - `self` must have been obtained from a call to [`World::as_unsafe_world_cell`]
156 /// (*not* `as_unsafe_world_cell_readonly` or any other method of construction that
157 /// does not provide mutable access to the entire world).
158 /// - This means that if you have an `UnsafeWorldCell` that you didn't create yourself,
159 /// it is likely *unsound* to call this method.
160 /// - The returned `&mut World` *must* be unique: it must never be allowed to exist
161 /// at the same time as any other borrows of the world or any accesses to its data.
162 /// This includes safe ways of accessing world data, such as [`UnsafeWorldCell::archetypes`].
163 /// - Note that the `&mut World` *may* exist at the same time as instances of `UnsafeWorldCell`,
164 /// so long as none of those instances are used to access world data in any way
165 /// while the mutable borrow is active.
166 ///
167 /// [//]: # (This test fails miri.)
168 /// ```no_run
169 /// # use bevy_ecs::prelude::*;
170 /// # #[derive(Component)] struct Player;
171 /// # fn store_but_dont_use<T>(_: T) {}
172 /// # let mut world = World::new();
173 /// // Make an UnsafeWorldCell.
174 /// let world_cell = world.as_unsafe_world_cell();
175 ///
176 /// // SAFETY: `world_cell` was originally created from `&mut World`.
177 /// // We must be sure not to access any world data while `world_mut` is active.
178 /// let world_mut = unsafe { world_cell.world_mut() };
179 ///
180 /// // We can still use `world_cell` so long as we don't access the world with it.
181 /// store_but_dont_use(world_cell);
182 ///
183 /// // !!This is unsound!! Even though this method is safe, we cannot call it until
184 /// // `world_mut` is no longer active.
185 /// let tick = world_cell.change_tick();
186 ///
187 /// // Use mutable access to spawn an entity.
188 /// world_mut.spawn(Player);
189 ///
190 /// // Since we never use `world_mut` after this, the borrow is released
191 /// // and we are once again allowed to access the world using `world_cell`.
192 /// let archetypes = world_cell.archetypes();
193 /// ```
194 #[inline]
195 pub unsafe fn world_mut(self) -> &'w mut World {
196 self.assert_allows_mutable_access();
197 // SAFETY:
198 // - caller ensures the created `&mut World` is the only borrow of world
199 unsafe { &mut *self.ptr }
200 }
201
202 /// Gets a reference to the [`&World`](World) this [`UnsafeWorldCell`] belongs to.
203 /// This can be used for arbitrary shared/readonly access.
204 ///
205 /// # Safety
206 /// - must have permission to access the whole world immutably
207 /// - there must be no live exclusive borrows of world data
208 /// - there must be no live exclusive borrow of world
209 #[inline]
210 pub unsafe fn world(self) -> &'w World {
211 // SAFETY:
212 // - caller ensures there is no `&mut World` this makes it okay to make a `&World`
213 // - caller ensures there are no mutable borrows of world data, this means the caller cannot
214 // misuse the returned `&World`
215 unsafe { self.unsafe_world() }
216 }
217
218 /// Gets a reference to the [`World`] this [`UnsafeWorldCell`] belong to.
219 /// This can be used for arbitrary read only access of world metadata
220 ///
221 /// You should attempt to use various safe methods on [`UnsafeWorldCell`] for
222 /// metadata access before using this method.
223 ///
224 /// # Safety
225 /// - must only be used to access world metadata
226 #[inline]
227 pub unsafe fn world_metadata(self) -> &'w World {
228 // SAFETY: caller ensures that returned reference is not used to violate aliasing rules
229 unsafe { self.unsafe_world() }
230 }
231
232 /// Variant on [`UnsafeWorldCell::world`] solely used for implementing this type's methods.
233 /// It allows having an `&World` even with live mutable borrows of components and resources
234 /// so the returned `&World` should not be handed out to safe code and care should be taken
235 /// when working with it.
236 ///
237 /// Deliberately private as the correct way to access data in a [`World`] that may have existing
238 /// mutable borrows of data inside it, is to use [`UnsafeWorldCell`].
239 ///
240 /// # Safety
241 /// - must not be used in a way that would conflict with any
242 /// live exclusive borrows of world data
243 #[inline]
244 unsafe fn unsafe_world(self) -> &'w World {
245 // SAFETY:
246 // - caller ensures that the returned `&World` is not used in a way that would conflict
247 // with any existing mutable borrows of world data
248 unsafe { &*self.ptr }
249 }
250
251 /// Retrieves this world's unique [ID](WorldId).
252 #[inline]
253 pub fn id(self) -> WorldId {
254 // SAFETY:
255 // - we only access world metadata
256 unsafe { self.world_metadata() }.id()
257 }
258
259 /// Retrieves this world's [`Entities`] collection.
260 #[inline]
261 pub fn entities(self) -> &'w Entities {
262 // SAFETY:
263 // - we only access world metadata
264 &unsafe { self.world_metadata() }.entities
265 }
266
267 /// Retrieves this world's [`Entities`] collection.
268 #[inline]
269 pub fn entities_allocator(self) -> &'w EntityAllocator {
270 // SAFETY:
271 // - we only access world metadata
272 &unsafe { self.world_metadata() }.allocator
273 }
274
275 /// Retrieves this world's [`Archetypes`] collection.
276 #[inline]
277 pub fn archetypes(self) -> &'w Archetypes {
278 // SAFETY:
279 // - we only access world metadata
280 &unsafe { self.world_metadata() }.archetypes
281 }
282
283 /// Retrieves this world's [`Components`] collection.
284 #[inline]
285 pub fn components(self) -> &'w Components {
286 // SAFETY:
287 // - we only access world metadata
288 &unsafe { self.world_metadata() }.components
289 }
290
291 /// Retrieves this world's collection of [removed components](RemovedComponentMessages).
292 pub fn removed_components(self) -> &'w RemovedComponentMessages {
293 // SAFETY:
294 // - we only access world metadata
295 &unsafe { self.world_metadata() }.removed_components
296 }
297
298 /// Retrieves this world's [`Observers`] collection.
299 pub(crate) fn observers(self) -> &'w Observers {
300 // SAFETY:
301 // - we only access world metadata
302 &unsafe { self.world_metadata() }.observers
303 }
304
305 /// Retrieves this world's [`Bundles`] collection.
306 #[inline]
307 pub fn bundles(self) -> &'w Bundles {
308 // SAFETY:
309 // - we only access world metadata
310 &unsafe { self.world_metadata() }.bundles
311 }
312
313 /// Gets the current change tick of this world.
314 #[inline]
315 pub fn change_tick(self) -> Tick {
316 // SAFETY:
317 // - we only access world metadata
318 unsafe { self.world_metadata() }.read_change_tick()
319 }
320
321 /// Returns the id of the last ECS event that was fired.
322 /// Used internally to ensure observers don't trigger multiple times for the same event.
323 #[inline]
324 pub fn last_trigger_id(&self) -> u32 {
325 // SAFETY:
326 // - we only access world metadata
327 unsafe { self.world_metadata() }.last_trigger_id()
328 }
329
330 /// Returns the [`Tick`] indicating the last time that [`World::clear_trackers`] was called.
331 ///
332 /// If this `UnsafeWorldCell` was created from inside of an exclusive system (a [`System`] that
333 /// takes `&mut World` as its first parameter), this will instead return the `Tick` indicating
334 /// the last time the system was run.
335 ///
336 /// See [`World::last_change_tick()`].
337 ///
338 /// [`System`]: crate::system::System
339 #[inline]
340 pub fn last_change_tick(self) -> Tick {
341 // SAFETY:
342 // - we only access world metadata
343 unsafe { self.world_metadata() }.last_change_tick()
344 }
345
346 /// Increments the world's current change tick and returns the old value.
347 #[inline]
348 pub fn increment_change_tick(self) -> Tick {
349 // SAFETY:
350 // - we only access world metadata
351 let change_tick = unsafe { &self.world_metadata().change_tick };
352 // NOTE: We can used a relaxed memory ordering here, since nothing
353 // other than the atomic value itself is relying on atomic synchronization
354 Tick::new(change_tick.fetch_add(1, Ordering::Relaxed))
355 }
356
357 /// Provides unchecked access to the internal data stores of the [`World`].
358 ///
359 /// # Safety
360 ///
361 /// The caller must ensure that this is only used to access world data
362 /// that this [`UnsafeWorldCell`] is allowed to.
363 /// As always, any mutable access to a component must not exist at the same
364 /// time as any other accesses to that same component.
365 #[inline]
366 pub unsafe fn storages(self) -> &'w Storages {
367 // SAFETY: The caller promises to only access world data allowed by this instance.
368 &unsafe { self.unsafe_world() }.storages
369 }
370
371 /// Retrieves an [`UnsafeEntityCell`] that exposes read and write operations for the given `entity`.
372 /// Similar to the [`UnsafeWorldCell`], you are in charge of making sure that no aliasing rules are violated.
373 #[inline]
374 pub fn get_entity(self, entity: Entity) -> Result<UnsafeEntityCell<'w>, EntityNotSpawnedError> {
375 let location = self.entities().get_spawned(entity)?;
376 Ok(UnsafeEntityCell::new(
377 self,
378 entity,
379 location,
380 self.last_change_tick(),
381 self.change_tick(),
382 ))
383 }
384
385 /// Retrieves an [`UnsafeEntityCell`] that exposes read and write operations for the given `entity`.
386 /// Similar to the [`UnsafeWorldCell`], you are in charge of making sure that no aliasing rules are violated.
387 #[inline]
388 pub fn get_entity_with_ticks(
389 self,
390 entity: Entity,
391 last_run: Tick,
392 this_run: Tick,
393 ) -> Result<UnsafeEntityCell<'w>, EntityNotSpawnedError> {
394 let location = self.entities().get_spawned(entity)?;
395 Ok(UnsafeEntityCell::new(
396 self, entity, location, last_run, this_run,
397 ))
398 }
399
400 /// Gets a reference to the resource of the given type if it exists
401 ///
402 /// # Safety
403 /// It is the caller's responsibility to ensure that
404 /// - the [`UnsafeWorldCell`] has permission to access the resource
405 /// - no mutable reference to the resource exists at the same time
406 #[inline]
407 pub unsafe fn get_resource<R: Resource>(self) -> Option<&'w R> {
408 let component_id = self.components().get_valid_resource_id(TypeId::of::<R>())?;
409 // SAFETY: caller ensures `self` has permission to access the resource
410 // caller also ensure that no mutable reference to the resource exists
411 unsafe {
412 self.get_resource_by_id(component_id)
413 // SAFETY: `component_id` was obtained from the type ID of `R`.
414 .map(|ptr| ptr.deref::<R>())
415 }
416 }
417
418 /// Gets a reference including change detection to the resource of the given type if it exists.
419 ///
420 /// # Safety
421 /// It is the caller's responsibility to ensure that
422 /// - the [`UnsafeWorldCell`] has permission to access the resource
423 /// - no mutable reference to the resource exists at the same time
424 #[inline]
425 pub unsafe fn get_resource_ref<R: Resource>(self) -> Option<Ref<'w, R>> {
426 let component_id = self.components().get_valid_resource_id(TypeId::of::<R>())?;
427
428 // SAFETY: caller ensures `self` has permission to access the resource
429 // caller also ensures that no mutable reference to the resource exists
430 let (ptr, ticks) = unsafe { self.get_resource_with_ticks(component_id)? };
431
432 // SAFETY: `component_id` was obtained from the type ID of `R`
433 let value = unsafe { ptr.deref::<R>() };
434
435 // SAFETY: caller ensures that no mutable reference to the resource exists
436 let ticks = unsafe {
437 ComponentTicksRef::from_tick_cells(ticks, self.last_change_tick(), self.change_tick())
438 };
439
440 Some(Ref { value, ticks })
441 }
442
443 /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
444 /// The returned pointer must not be used to modify the resource, and must not be
445 /// dereferenced after the borrow of the [`World`] ends.
446 ///
447 /// **You should prefer to use the typed API [`UnsafeWorldCell::get_resource`] where possible and only
448 /// use this in cases where the actual types are not known at compile time.**
449 ///
450 /// # Safety
451 /// It is the caller's responsibility to ensure that
452 /// - the [`UnsafeWorldCell`] has permission to access the resource
453 /// - no mutable reference to the resource exists at the same time
454 #[inline]
455 pub unsafe fn get_resource_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
456 // SAFETY: caller ensures that `self` has permission to access `R`
457 // caller ensures that no mutable reference exists to `R`
458 unsafe { self.storages() }
459 .resources
460 .get(component_id)?
461 .get_data()
462 }
463
464 /// Gets a reference to the non-send resource of the given type if it exists
465 ///
466 /// # Safety
467 /// It is the caller's responsibility to ensure that
468 /// - the [`UnsafeWorldCell`] has permission to access the resource
469 /// - no mutable reference to the resource exists at the same time
470 #[inline]
471 pub unsafe fn get_non_send_resource<R: 'static>(self) -> Option<&'w R> {
472 let component_id = self.components().get_valid_resource_id(TypeId::of::<R>())?;
473 // SAFETY: caller ensures that `self` has permission to access `R`
474 // caller ensures that no mutable reference exists to `R`
475 unsafe {
476 self.get_non_send_resource_by_id(component_id)
477 // SAFETY: `component_id` was obtained from `TypeId::of::<R>()`
478 .map(|ptr| ptr.deref::<R>())
479 }
480 }
481
482 /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
483 /// The returned pointer must not be used to modify the resource, and must not be
484 /// dereferenced after the immutable borrow of the [`World`] ends.
485 ///
486 /// **You should prefer to use the typed API [`UnsafeWorldCell::get_non_send_resource`] where possible and only
487 /// use this in cases where the actual types are not known at compile time.**
488 ///
489 /// # Panics
490 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
491 ///
492 /// # Safety
493 /// It is the caller's responsibility to ensure that
494 /// - the [`UnsafeWorldCell`] has permission to access the resource
495 /// - no mutable reference to the resource exists at the same time
496 #[inline]
497 pub unsafe fn get_non_send_resource_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
498 // SAFETY: we only access data on world that the caller has ensured is unaliased and we have
499 // permission to access.
500 unsafe { self.storages() }
501 .non_send_resources
502 .get(component_id)?
503 .get_data()
504 }
505
506 /// Gets a mutable reference to the resource of the given type if it exists
507 ///
508 /// # Safety
509 /// It is the caller's responsibility to ensure that
510 /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
511 /// - no other references to the resource exist at the same time
512 #[inline]
513 pub unsafe fn get_resource_mut<R: Resource>(self) -> Option<Mut<'w, R>> {
514 self.assert_allows_mutable_access();
515 let component_id = self.components().get_valid_resource_id(TypeId::of::<R>())?;
516 // SAFETY:
517 // - caller ensures `self` has permission to access the resource mutably
518 // - caller ensures no other references to the resource exist
519 unsafe {
520 self.get_resource_mut_by_id(component_id)
521 // `component_id` was gotten from `TypeId::of::<R>()`
522 .map(|ptr| ptr.with_type::<R>())
523 }
524 }
525
526 /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
527 /// The returned pointer may be used to modify the resource, as long as the mutable borrow
528 /// of the [`UnsafeWorldCell`] is still valid.
529 ///
530 /// **You should prefer to use the typed API [`UnsafeWorldCell::get_resource_mut`] where possible and only
531 /// use this in cases where the actual types are not known at compile time.**
532 ///
533 /// # Safety
534 /// It is the caller's responsibility to ensure that
535 /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
536 /// - no other references to the resource exist at the same time
537 #[inline]
538 pub unsafe fn get_resource_mut_by_id(
539 self,
540 component_id: ComponentId,
541 ) -> Option<MutUntyped<'w>> {
542 self.assert_allows_mutable_access();
543 // SAFETY: we only access data that the caller has ensured is unaliased and `self`
544 // has permission to access.
545 let (ptr, ticks) = unsafe { self.storages() }
546 .resources
547 .get(component_id)?
548 .get_with_ticks()?;
549
550 // SAFETY:
551 // - index is in-bounds because the column is initialized and non-empty
552 // - the caller promises that no other reference to the ticks of the same row can exist at the same time
553 let ticks = unsafe {
554 ComponentTicksMut::from_tick_cells(ticks, self.last_change_tick(), self.change_tick())
555 };
556
557 Some(MutUntyped {
558 // SAFETY:
559 // - caller ensures that `self` has permission to access the resource
560 // - caller ensures that the resource is unaliased
561 value: unsafe { ptr.assert_unique() },
562 ticks,
563 })
564 }
565
566 /// Gets a mutable reference to the non-send resource of the given type if it exists
567 ///
568 /// # Safety
569 /// It is the caller's responsibility to ensure that
570 /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
571 /// - no other references to the resource exist at the same time
572 #[inline]
573 pub unsafe fn get_non_send_resource_mut<R: 'static>(self) -> Option<Mut<'w, R>> {
574 self.assert_allows_mutable_access();
575 let component_id = self.components().get_valid_resource_id(TypeId::of::<R>())?;
576 // SAFETY:
577 // - caller ensures that `self` has permission to access the resource
578 // - caller ensures that the resource is unaliased
579 unsafe {
580 self.get_non_send_resource_mut_by_id(component_id)
581 // SAFETY: `component_id` was gotten by `TypeId::of::<R>()`
582 .map(|ptr| ptr.with_type::<R>())
583 }
584 }
585
586 /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
587 /// The returned pointer may be used to modify the resource, as long as the mutable borrow
588 /// of the [`World`] is still valid.
589 ///
590 /// **You should prefer to use the typed API [`UnsafeWorldCell::get_non_send_resource_mut`] where possible and only
591 /// use this in cases where the actual types are not known at compile time.**
592 ///
593 /// # Panics
594 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
595 ///
596 /// # Safety
597 /// It is the caller's responsibility to ensure that
598 /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
599 /// - no other references to the resource exist at the same time
600 #[inline]
601 pub unsafe fn get_non_send_resource_mut_by_id(
602 self,
603 component_id: ComponentId,
604 ) -> Option<MutUntyped<'w>> {
605 self.assert_allows_mutable_access();
606 let change_tick = self.change_tick();
607 // SAFETY: we only access data that the caller has ensured is unaliased and `self`
608 // has permission to access.
609 let (ptr, ticks) = unsafe { self.storages() }
610 .non_send_resources
611 .get(component_id)?
612 .get_with_ticks()?;
613
614 let ticks =
615 // SAFETY: This function has exclusive access to the world so nothing aliases `ticks`.
616 // - index is in-bounds because the column is initialized and non-empty
617 // - no other reference to the ticks of the same row can exist at the same time
618 unsafe { ComponentTicksMut::from_tick_cells(ticks, self.last_change_tick(), change_tick) };
619
620 Some(MutUntyped {
621 // SAFETY: This function has exclusive access to the world so nothing aliases `ptr`.
622 value: unsafe { ptr.assert_unique() },
623 ticks,
624 })
625 }
626
627 // Shorthand helper function for getting the data and change ticks for a resource.
628 /// # Safety
629 /// It is the caller's responsibility to ensure that
630 /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
631 /// - no mutable references to the resource exist at the same time
632 #[inline]
633 pub(crate) unsafe fn get_resource_with_ticks(
634 self,
635 component_id: ComponentId,
636 ) -> Option<(Ptr<'w>, ComponentTickCells<'w>)> {
637 // SAFETY:
638 // - caller ensures there is no `&mut World`
639 // - caller ensures there are no mutable borrows of this resource
640 // - caller ensures that we have permission to access this resource
641 unsafe { self.storages() }
642 .resources
643 .get(component_id)?
644 .get_with_ticks()
645 }
646
647 // Shorthand helper function for getting the data and change ticks for a resource.
648 /// # Panics
649 /// This function will panic if it isn't called from the same thread that the resource was inserted from.
650 ///
651 /// # Safety
652 /// It is the caller's responsibility to ensure that
653 /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
654 /// - no mutable references to the resource exist at the same time
655 #[inline]
656 pub(crate) unsafe fn get_non_send_with_ticks(
657 self,
658 component_id: ComponentId,
659 ) -> Option<(Ptr<'w>, ComponentTickCells<'w>)> {
660 // SAFETY:
661 // - caller ensures there is no `&mut World`
662 // - caller ensures there are no mutable borrows of this resource
663 // - caller ensures that we have permission to access this resource
664 unsafe { self.storages() }
665 .non_send_resources
666 .get(component_id)?
667 .get_with_ticks()
668 }
669
670 // Returns a mutable reference to the underlying world's [`CommandQueue`].
671 /// # Safety
672 /// It is the caller's responsibility to ensure that
673 /// - the [`UnsafeWorldCell`] has permission to access the queue mutably
674 /// - no mutable references to the queue exist at the same time
675 pub(crate) unsafe fn get_raw_command_queue(self) -> RawCommandQueue {
676 self.assert_allows_mutable_access();
677 // SAFETY:
678 // - caller ensures there are no existing mutable references
679 // - caller ensures that we have permission to access the queue
680 unsafe { (*self.ptr).command_queue.clone() }
681 }
682
683 /// # Safety
684 /// It is the caller's responsibility to ensure that there are no outstanding
685 /// references to `last_trigger_id`.
686 pub(crate) unsafe fn increment_trigger_id(self) {
687 self.assert_allows_mutable_access();
688 // SAFETY: Caller ensure there are no outstanding references
689 unsafe {
690 (*self.ptr).last_trigger_id = (*self.ptr).last_trigger_id.wrapping_add(1);
691 }
692 }
693
694 /// Convenience method for accessing the world's default error handler,
695 ///
696 /// # Safety
697 /// Must have read access to [`DefaultErrorHandler`].
698 #[inline]
699 pub unsafe fn default_error_handler(&self) -> ErrorHandler {
700 // SAFETY: Upheld by caller
701 unsafe { self.get_resource::<DefaultErrorHandler>() }
702 .copied()
703 .unwrap_or_default()
704 .0
705 }
706}
707
708impl Debug for UnsafeWorldCell<'_> {
709 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
710 // SAFETY: World's Debug implementation only accesses metadata.
711 Debug::fmt(unsafe { self.world_metadata() }, f)
712 }
713}
714
715/// An interior-mutable reference to a particular [`Entity`] and all of its components
716#[derive(Copy, Clone)]
717pub struct UnsafeEntityCell<'w> {
718 world: UnsafeWorldCell<'w>,
719 entity: Entity,
720 location: EntityLocation,
721 last_run: Tick,
722 this_run: Tick,
723}
724
725impl<'w> UnsafeEntityCell<'w> {
726 #[inline]
727 pub(crate) fn new(
728 world: UnsafeWorldCell<'w>,
729 entity: Entity,
730 location: EntityLocation,
731 last_run: Tick,
732 this_run: Tick,
733 ) -> Self {
734 UnsafeEntityCell {
735 world,
736 entity,
737 location,
738 last_run,
739 this_run,
740 }
741 }
742
743 /// Returns the [ID](Entity) of the current entity.
744 #[inline]
745 #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
746 pub fn id(self) -> Entity {
747 self.entity
748 }
749
750 /// Gets metadata indicating the location where the current entity is stored.
751 #[inline]
752 pub fn location(self) -> EntityLocation {
753 self.location
754 }
755
756 /// Returns the archetype that the current entity belongs to.
757 #[inline]
758 pub fn archetype(self) -> &'w Archetype {
759 &self.world.archetypes()[self.location.archetype_id]
760 }
761
762 /// Gets the world that the current entity belongs to.
763 #[inline]
764 pub fn world(self) -> UnsafeWorldCell<'w> {
765 self.world
766 }
767
768 /// Returns `true` if the current entity has a component of type `T`.
769 /// Otherwise, this returns `false`.
770 ///
771 /// ## Notes
772 ///
773 /// If you do not know the concrete type of a component, consider using
774 /// [`Self::contains_id`] or [`Self::contains_type_id`].
775 #[inline]
776 pub fn contains<T: Component>(self) -> bool {
777 self.contains_type_id(TypeId::of::<T>())
778 }
779
780 /// Returns `true` if the current entity has a component identified by `component_id`.
781 /// Otherwise, this returns false.
782 ///
783 /// ## Notes
784 ///
785 /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
786 /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
787 /// [`Self::contains_type_id`].
788 #[inline]
789 pub fn contains_id(self, component_id: ComponentId) -> bool {
790 self.archetype().contains(component_id)
791 }
792
793 /// Returns `true` if the current entity has a component with the type identified by `type_id`.
794 /// Otherwise, this returns false.
795 ///
796 /// ## Notes
797 ///
798 /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
799 /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
800 #[inline]
801 pub fn contains_type_id(self, type_id: TypeId) -> bool {
802 let Some(id) = self.world.components().get_id(type_id) else {
803 return false;
804 };
805 self.contains_id(id)
806 }
807
808 /// # Safety
809 /// It is the caller's responsibility to ensure that
810 /// - the [`UnsafeEntityCell`] has permission to access the component
811 /// - no other mutable references to the component exist at the same time
812 #[inline]
813 pub unsafe fn get<T: Component>(self) -> Option<&'w T> {
814 let component_id = self.world.components().get_valid_id(TypeId::of::<T>())?;
815 // SAFETY:
816 // - `storage_type` is correct (T component_id + T::STORAGE_TYPE)
817 // - `location` is valid
818 // - proper aliasing is promised by caller
819 unsafe {
820 get_component(
821 self.world,
822 component_id,
823 T::STORAGE_TYPE,
824 self.entity,
825 self.location,
826 )
827 // SAFETY: returned component is of type T
828 .map(|value| value.deref::<T>())
829 }
830 }
831
832 /// # Safety
833 /// It is the caller's responsibility to ensure that
834 /// - the [`UnsafeEntityCell`] has permission to access the component
835 /// - no other mutable references to the component exist at the same time
836 #[inline]
837 pub unsafe fn get_ref<T: Component>(self) -> Option<Ref<'w, T>> {
838 let last_change_tick = self.last_run;
839 let change_tick = self.this_run;
840 let component_id = self.world.components().get_valid_id(TypeId::of::<T>())?;
841
842 // SAFETY:
843 // - `storage_type` is correct (T component_id + T::STORAGE_TYPE)
844 // - `location` is valid
845 // - proper aliasing is promised by caller
846 unsafe {
847 get_component_and_ticks(
848 self.world,
849 component_id,
850 T::STORAGE_TYPE,
851 self.entity,
852 self.location,
853 )
854 .map(|(value, cells)| Ref {
855 // SAFETY: returned component is of type T
856 value: value.deref::<T>(),
857 ticks: ComponentTicksRef::from_tick_cells(cells, last_change_tick, change_tick),
858 })
859 }
860 }
861
862 /// Retrieves the change ticks for the given component. This can be useful for implementing change
863 /// detection in custom runtimes.
864 ///
865 /// # Safety
866 /// It is the caller's responsibility to ensure that
867 /// - the [`UnsafeEntityCell`] has permission to access the component
868 /// - no other mutable references to the component exist at the same time
869 #[inline]
870 pub unsafe fn get_change_ticks<T: Component>(self) -> Option<ComponentTicks> {
871 let component_id = self.world.components().get_valid_id(TypeId::of::<T>())?;
872
873 // SAFETY:
874 // - entity location is valid
875 // - proper world access is promised by caller
876 unsafe {
877 get_ticks(
878 self.world,
879 component_id,
880 T::STORAGE_TYPE,
881 self.entity,
882 self.location,
883 )
884 }
885 }
886
887 /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
888 /// detection in custom runtimes.
889 ///
890 /// **You should prefer to use the typed API [`UnsafeEntityCell::get_change_ticks`] where possible and only
891 /// use this in cases where the actual component types are not known at
892 /// compile time.**
893 ///
894 /// # Safety
895 /// It is the caller's responsibility to ensure that
896 /// - the [`UnsafeEntityCell`] has permission to access the component
897 /// - no other mutable references to the component exist at the same time
898 #[inline]
899 pub unsafe fn get_change_ticks_by_id(
900 &self,
901 component_id: ComponentId,
902 ) -> Option<ComponentTicks> {
903 let info = self.world.components().get_info(component_id)?;
904 // SAFETY:
905 // - entity location and entity is valid
906 // - world access is immutable, lifetime tied to `&self`
907 // - the storage type provided is correct for T
908 unsafe {
909 get_ticks(
910 self.world,
911 component_id,
912 info.storage_type(),
913 self.entity,
914 self.location,
915 )
916 }
917 }
918
919 /// # Safety
920 /// It is the caller's responsibility to ensure that
921 /// - the [`UnsafeEntityCell`] has permission to access the component mutably
922 /// - no other references to the component exist at the same time
923 #[inline]
924 pub unsafe fn get_mut<T: Component<Mutability = Mutable>>(self) -> Option<Mut<'w, T>> {
925 // SAFETY:
926 // - trait bound `T: Component<Mutability = Mutable>` ensures component is mutable
927 // - same safety requirements
928 unsafe { self.get_mut_assume_mutable() }
929 }
930
931 /// # Safety
932 /// It is the caller's responsibility to ensure that
933 /// - the [`UnsafeEntityCell`] has permission to access the component mutably
934 /// - no other references to the component exist at the same time
935 /// - the component `T` is mutable
936 #[inline]
937 pub unsafe fn get_mut_assume_mutable<T: Component>(self) -> Option<Mut<'w, T>> {
938 // SAFETY: same safety requirements
939 unsafe { self.get_mut_using_ticks_assume_mutable(self.last_run, self.this_run) }
940 }
941
942 /// # Safety
943 /// It is the caller's responsibility to ensure that
944 /// - the [`UnsafeEntityCell`] has permission to access the component mutably
945 /// - no other references to the component exist at the same time
946 /// - The component `T` is mutable
947 #[inline]
948 pub(crate) unsafe fn get_mut_using_ticks_assume_mutable<T: Component>(
949 &self,
950 last_change_tick: Tick,
951 change_tick: Tick,
952 ) -> Option<Mut<'w, T>> {
953 self.world.assert_allows_mutable_access();
954
955 let component_id = self.world.components().get_valid_id(TypeId::of::<T>())?;
956
957 // SAFETY:
958 // - `storage_type` is correct
959 // - `location` is valid
960 // - aliasing rules are ensured by caller
961 unsafe {
962 get_component_and_ticks(
963 self.world,
964 component_id,
965 T::STORAGE_TYPE,
966 self.entity,
967 self.location,
968 )
969 .map(|(value, cells)| Mut {
970 // SAFETY: returned component is of type T
971 value: value.assert_unique().deref_mut::<T>(),
972 ticks: ComponentTicksMut::from_tick_cells(cells, last_change_tick, change_tick),
973 })
974 }
975 }
976
977 /// Returns read-only components for the current entity that match the query `Q`,
978 /// or `None` if the entity does not have the components required by the query `Q`.
979 ///
980 /// # Safety
981 /// It is the caller's responsibility to ensure that
982 /// - the [`UnsafeEntityCell`] has permission to access the queried data immutably
983 /// - no mutable references to the queried data exist at the same time
984 /// - The `QueryData` does not provide aliasing mutable references to the same component.
985 pub(crate) unsafe fn get_components<Q: ReleaseStateQueryData>(
986 &self,
987 ) -> Result<Q::Item<'w, 'static>, QueryAccessError> {
988 // SAFETY: World is only used to access query data and initialize query state
989 let state = unsafe {
990 let world = self.world().world();
991 Q::get_state(world.components()).ok_or(QueryAccessError::ComponentNotRegistered)?
992 };
993 let location = self.location();
994 // SAFETY: Location is guaranteed to exist
995 let archetype = unsafe {
996 self.world
997 .archetypes()
998 .get(location.archetype_id)
999 .debug_checked_unwrap()
1000 };
1001 if Q::matches_component_set(&state, &|id| archetype.contains(id)) {
1002 // SAFETY: state was initialized above using the world passed into this function
1003 let mut fetch =
1004 unsafe { Q::init_fetch(self.world, &state, self.last_run, self.this_run) };
1005 // SAFETY: Table is guaranteed to exist
1006 let table = unsafe {
1007 self.world
1008 .storages()
1009 .tables
1010 .get(location.table_id)
1011 .debug_checked_unwrap()
1012 };
1013 // SAFETY: Archetype and table are from the same world used to initialize state and fetch.
1014 // Table corresponds to archetype. State is the same state used to init fetch above.
1015 unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) }
1016 // SAFETY: Called after set_archetype above. Entity and location are guaranteed to exist.
1017 let item = unsafe { Q::fetch(&state, &mut fetch, self.id(), location.table_row) };
1018 item.map(Q::release_state)
1019 .ok_or(QueryAccessError::EntityDoesNotMatch)
1020 } else {
1021 Err(QueryAccessError::EntityDoesNotMatch)
1022 }
1023 }
1024
1025 /// Gets the component of the given [`ComponentId`] from the entity.
1026 ///
1027 /// **You should prefer to use the typed API where possible and only
1028 /// use this in cases where the actual component types are not known at
1029 /// compile time.**
1030 ///
1031 /// Unlike [`UnsafeEntityCell::get`], this returns a raw pointer to the component,
1032 /// which is only valid while the `'w` borrow of the lifetime is active.
1033 ///
1034 /// # Safety
1035 /// It is the caller's responsibility to ensure that
1036 /// - the [`UnsafeEntityCell`] has permission to access the component
1037 /// - no other mutable references to the component exist at the same time
1038 #[inline]
1039 pub unsafe fn get_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
1040 let info = self.world.components().get_info(component_id)?;
1041 // SAFETY: entity_location is valid, component_id is valid as checked by the line above
1042 unsafe {
1043 get_component(
1044 self.world,
1045 component_id,
1046 info.storage_type(),
1047 self.entity,
1048 self.location,
1049 )
1050 }
1051 }
1052
1053 /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
1054 /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
1055 ///
1056 /// **You should prefer to use the typed API [`UnsafeEntityCell::get_mut`] where possible and only
1057 /// use this in cases where the actual types are not known at compile time.**
1058 ///
1059 /// # Safety
1060 /// It is the caller's responsibility to ensure that
1061 /// - the [`UnsafeEntityCell`] has permission to access the component mutably
1062 /// - no other references to the component exist at the same time
1063 #[inline]
1064 pub unsafe fn get_mut_by_id(
1065 self,
1066 component_id: ComponentId,
1067 ) -> Result<MutUntyped<'w>, GetEntityMutByIdError> {
1068 self.world.assert_allows_mutable_access();
1069
1070 let info = self
1071 .world
1072 .components()
1073 .get_info(component_id)
1074 .ok_or(GetEntityMutByIdError::InfoNotFound)?;
1075
1076 // If a component is immutable then a mutable reference to it doesn't exist
1077 if !info.mutable() {
1078 return Err(GetEntityMutByIdError::ComponentIsImmutable);
1079 }
1080
1081 // SAFETY: entity_location is valid, component_id is valid as checked by the line above
1082 unsafe {
1083 get_component_and_ticks(
1084 self.world,
1085 component_id,
1086 info.storage_type(),
1087 self.entity,
1088 self.location,
1089 )
1090 .map(|(value, cells)| MutUntyped {
1091 // SAFETY: world access validated by caller and ties world lifetime to `MutUntyped` lifetime
1092 value: value.assert_unique(),
1093 ticks: ComponentTicksMut::from_tick_cells(cells, self.last_run, self.this_run),
1094 })
1095 .ok_or(GetEntityMutByIdError::ComponentNotFound)
1096 }
1097 }
1098
1099 /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
1100 /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
1101 /// This method assumes the [`Component`] is mutable, skipping that check.
1102 ///
1103 /// **You should prefer to use the typed API [`UnsafeEntityCell::get_mut_assume_mutable`] where possible and only
1104 /// use this in cases where the actual types are not known at compile time.**
1105 ///
1106 /// # Safety
1107 /// It is the caller's responsibility to ensure that
1108 /// - the [`UnsafeEntityCell`] has permission to access the component mutably
1109 /// - no other references to the component exist at the same time
1110 /// - the component `T` is mutable
1111 #[inline]
1112 pub unsafe fn get_mut_assume_mutable_by_id(
1113 self,
1114 component_id: ComponentId,
1115 ) -> Result<MutUntyped<'w>, GetEntityMutByIdError> {
1116 self.world.assert_allows_mutable_access();
1117
1118 let info = self
1119 .world
1120 .components()
1121 .get_info(component_id)
1122 .ok_or(GetEntityMutByIdError::InfoNotFound)?;
1123
1124 // SAFETY: entity_location is valid, component_id is valid as checked by the line above
1125 unsafe {
1126 get_component_and_ticks(
1127 self.world,
1128 component_id,
1129 info.storage_type(),
1130 self.entity,
1131 self.location,
1132 )
1133 .map(|(value, cells)| MutUntyped {
1134 // SAFETY: world access validated by caller and ties world lifetime to `MutUntyped` lifetime
1135 value: value.assert_unique(),
1136 ticks: ComponentTicksMut::from_tick_cells(cells, self.last_run, self.this_run),
1137 })
1138 .ok_or(GetEntityMutByIdError::ComponentNotFound)
1139 }
1140 }
1141
1142 /// Returns the source code location from which this entity has been spawned.
1143 pub fn spawned_by(self) -> MaybeLocation {
1144 self.world()
1145 .entities()
1146 .entity_get_spawned_or_despawned_by(self.entity)
1147 .map(|o| o.unwrap())
1148 }
1149
1150 /// Returns the [`Tick`] at which this entity has been spawned.
1151 pub fn spawn_tick(self) -> Tick {
1152 // SAFETY: UnsafeEntityCell is only constructed for living entities and offers no despawn method
1153 unsafe {
1154 self.world()
1155 .entities()
1156 .entity_get_spawned_or_despawned_unchecked(self.entity)
1157 .1
1158 }
1159 }
1160}
1161
1162/// Error that may be returned when calling [`UnsafeEntityCell::get_mut_by_id`].
1163#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
1164pub enum GetEntityMutByIdError {
1165 /// The [`ComponentInfo`](crate::component::ComponentInfo) could not be found.
1166 #[error("the `ComponentInfo` could not be found")]
1167 InfoNotFound,
1168 /// The [`Component`] is immutable. Creating a mutable reference violates its
1169 /// invariants.
1170 #[error("the `Component` is immutable")]
1171 ComponentIsImmutable,
1172 /// This [`Entity`] does not have the desired [`Component`].
1173 #[error("the `Component` could not be found")]
1174 ComponentNotFound,
1175}
1176
1177impl<'w> UnsafeWorldCell<'w> {
1178 #[inline]
1179 /// # Safety
1180 /// - the returned `Table` is only used in ways that this [`UnsafeWorldCell`] has permission for.
1181 /// - the returned `Table` is only used in ways that would not conflict with any existing borrows of world data.
1182 unsafe fn fetch_table(self, location: EntityLocation) -> Option<&'w Table> {
1183 // SAFETY:
1184 // - caller ensures returned data is not misused and we have not created any borrows of component/resource data
1185 // - `location` contains a valid `TableId`, so getting the table won't fail
1186 unsafe { self.storages().tables.get(location.table_id) }
1187 }
1188
1189 #[inline]
1190 /// # Safety
1191 /// - the returned `ComponentSparseSet` is only used in ways that this [`UnsafeWorldCell`] has permission for.
1192 /// - the returned `ComponentSparseSet` is only used in ways that would not conflict with any existing
1193 /// borrows of world data.
1194 unsafe fn fetch_sparse_set(self, component_id: ComponentId) -> Option<&'w ComponentSparseSet> {
1195 // SAFETY: caller ensures returned data is not misused and we have not created any borrows
1196 // of component/resource data
1197 unsafe { self.storages() }.sparse_sets.get(component_id)
1198 }
1199}
1200
1201/// Get an untyped pointer to a particular [`Component`] on a particular [`Entity`] in the provided [`World`].
1202///
1203/// # Safety
1204/// - `location` must refer to an archetype that contains `entity`
1205/// the archetype
1206/// - `component_id` must be valid
1207/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
1208/// - the caller must ensure that no aliasing rules are violated
1209#[inline]
1210unsafe fn get_component(
1211 world: UnsafeWorldCell<'_>,
1212 component_id: ComponentId,
1213 storage_type: StorageType,
1214 entity: Entity,
1215 location: EntityLocation,
1216) -> Option<Ptr<'_>> {
1217 // SAFETY: component_id exists and is therefore valid
1218 match storage_type {
1219 StorageType::Table => {
1220 let table = world.fetch_table(location)?;
1221 // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
1222 table.get_component(component_id, location.table_row)
1223 }
1224 StorageType::SparseSet => world.fetch_sparse_set(component_id)?.get(entity),
1225 }
1226}
1227
1228/// Get an untyped pointer to a particular [`Component`] and its [`ComponentTicks`]
1229///
1230/// # Safety
1231/// - `location` must refer to an archetype that contains `entity`
1232/// - `component_id` must be valid
1233/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
1234/// - the caller must ensure that no aliasing rules are violated
1235#[inline]
1236unsafe fn get_component_and_ticks(
1237 world: UnsafeWorldCell<'_>,
1238 component_id: ComponentId,
1239 storage_type: StorageType,
1240 entity: Entity,
1241 location: EntityLocation,
1242) -> Option<(Ptr<'_>, ComponentTickCells<'_>)> {
1243 match storage_type {
1244 StorageType::Table => {
1245 let table = world.fetch_table(location)?;
1246
1247 // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
1248 Some((
1249 table.get_component(component_id, location.table_row)?,
1250 ComponentTickCells {
1251 added: table
1252 .get_added_tick(component_id, location.table_row)
1253 .debug_checked_unwrap(),
1254 changed: table
1255 .get_changed_tick(component_id, location.table_row)
1256 .debug_checked_unwrap(),
1257 changed_by: table
1258 .get_changed_by(component_id, location.table_row)
1259 .map(|changed_by| changed_by.debug_checked_unwrap()),
1260 },
1261 ))
1262 }
1263 StorageType::SparseSet => world.fetch_sparse_set(component_id)?.get_with_ticks(entity),
1264 }
1265}
1266
1267/// Get an untyped pointer to the [`ComponentTicks`] on a particular [`Entity`]
1268///
1269/// # Safety
1270/// - `location` must refer to an archetype that contains `entity`
1271/// the archetype
1272/// - `component_id` must be valid
1273/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
1274/// - the caller must ensure that no aliasing rules are violated
1275#[inline]
1276unsafe fn get_ticks(
1277 world: UnsafeWorldCell<'_>,
1278 component_id: ComponentId,
1279 storage_type: StorageType,
1280 entity: Entity,
1281 location: EntityLocation,
1282) -> Option<ComponentTicks> {
1283 match storage_type {
1284 StorageType::Table => {
1285 let table = world.fetch_table(location)?;
1286 // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
1287 table.get_ticks_unchecked(component_id, location.table_row)
1288 }
1289 StorageType::SparseSet => world.fetch_sparse_set(component_id)?.get_ticks(entity),
1290 }
1291}
1292
1293impl ContainsEntity for UnsafeEntityCell<'_> {
1294 fn entity(&self) -> Entity {
1295 self.id()
1296 }
1297}
1298
1299#[cfg(test)]
1300mod tests {
1301 use super::*;
1302
1303 #[test]
1304 #[should_panic = "is forbidden"]
1305 fn as_unsafe_world_cell_readonly_world_mut_forbidden() {
1306 let world = World::new();
1307 let world_cell = world.as_unsafe_world_cell_readonly();
1308 // SAFETY: this invalid usage will be caught by a runtime panic.
1309 let _ = unsafe { world_cell.world_mut() };
1310 }
1311
1312 #[derive(Resource)]
1313 struct R;
1314
1315 #[test]
1316 #[should_panic = "is forbidden"]
1317 fn as_unsafe_world_cell_readonly_resource_mut_forbidden() {
1318 let mut world = World::new();
1319 world.insert_resource(R);
1320 let world_cell = world.as_unsafe_world_cell_readonly();
1321 // SAFETY: this invalid usage will be caught by a runtime panic.
1322 let _ = unsafe { world_cell.get_resource_mut::<R>() };
1323 }
1324
1325 #[derive(Component)]
1326 struct C;
1327
1328 #[test]
1329 #[should_panic = "is forbidden"]
1330 fn as_unsafe_world_cell_readonly_component_mut_forbidden() {
1331 let mut world = World::new();
1332 let entity = world.spawn(C).id();
1333 let world_cell = world.as_unsafe_world_cell_readonly();
1334 let entity_cell = world_cell.get_entity(entity).unwrap();
1335 // SAFETY: this invalid usage will be caught by a runtime panic.
1336 let _ = unsafe { entity_cell.get_mut::<C>() };
1337 }
1338}