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