Skip to content

Commit 3b39018

Browse files
reuse InteriorMutableEntityRef more
1 parent e20ca25 commit 3b39018

File tree

1 file changed

+37
-96
lines changed

1 file changed

+37
-96
lines changed

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 37 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ impl<'w> EntityRef<'w> {
4242
}
4343
}
4444

45+
fn as_interior_mutable_readonly(&self) -> InteriorMutableEntityRef<'w> {
46+
InteriorMutableEntityRef::new(
47+
self.world.as_interior_mutable_readonly(),
48+
self.entity,
49+
self.location,
50+
)
51+
}
52+
4553
#[inline]
4654
#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
4755
pub fn id(&self) -> Entity {
@@ -80,39 +88,16 @@ impl<'w> EntityRef<'w> {
8088

8189
#[inline]
8290
pub fn get<T: Component>(&self) -> Option<&'w T> {
83-
// SAFETY:
84-
// - entity location and entity is valid
85-
// - the storage type provided is correct for T
86-
// - world access is immutable, lifetime tied to `&self`
87-
unsafe {
88-
self.world
89-
.get_component_with_type(
90-
TypeId::of::<T>(),
91-
T::Storage::STORAGE_TYPE,
92-
self.entity,
93-
self.location,
94-
)
95-
// SAFETY: returned component is of type T
96-
.map(|value| value.deref::<T>())
97-
}
91+
// SAFETY: &self implies shared access for duration of returned value
92+
unsafe { self.as_interior_mutable_readonly().get::<T>() }
9893
}
9994

10095
/// Retrieves the change ticks for the given component. This can be useful for implementing change
10196
/// detection in custom runtimes.
10297
#[inline]
10398
pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {
104-
// SAFETY:
105-
// - entity location and entity is valid
106-
// - world access is immutable, lifetime tied to `&self`
107-
// - the storage type provided is correct for T
108-
unsafe {
109-
self.world.get_ticks_with_type(
110-
TypeId::of::<T>(),
111-
T::Storage::STORAGE_TYPE,
112-
self.entity,
113-
self.location,
114-
)
115-
}
99+
// SAFETY: &self implies shared access
100+
unsafe { self.as_interior_mutable_readonly().get_change_ticks::<T>() }
116101
}
117102

118103
/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
@@ -123,18 +108,10 @@ impl<'w> EntityRef<'w> {
123108
/// compile time.**
124109
#[inline]
125110
pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {
126-
let info = self.world.components().get_info(component_id)?;
127-
// SAFETY:
128-
// - entity location and entity is valid
129-
// - world access is immutable, lifetime tied to `&self`
130-
// - the storage type provided is correct for T
111+
// SAFETY: &self implies shared access
131112
unsafe {
132-
self.world.get_ticks(
133-
component_id,
134-
info.storage_type(),
135-
self.entity,
136-
self.location,
137-
)
113+
self.as_interior_mutable_readonly()
114+
.get_change_ticks_by_id(component_id)
138115
}
139116
}
140117
}
@@ -150,19 +127,8 @@ impl<'w> EntityRef<'w> {
150127
/// which is only valid while the `'w` borrow of the lifetime is active.
151128
#[inline]
152129
pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'w>> {
153-
let info = self.world.components().get_info(component_id)?;
154-
// SAFETY:
155-
// - entity_location and entity are valid
156-
// - component_id is valid as checked by the line above
157-
// - the storage type is accurate as checked by the fetched ComponentInfo
158-
unsafe {
159-
self.world.get_component(
160-
component_id,
161-
info.storage_type(),
162-
self.entity,
163-
self.location,
164-
)
165-
}
130+
// SAFETY: &self implies shared access for duration of returned value
131+
unsafe { self.as_interior_mutable_readonly().get_by_id(component_id) }
166132
}
167133
}
168134

@@ -182,6 +148,17 @@ pub struct EntityMut<'w> {
182148
}
183149

184150
impl<'w> EntityMut<'w> {
151+
fn as_interior_mutable_readonly(&self) -> InteriorMutableEntityRef<'_> {
152+
InteriorMutableEntityRef::new(
153+
self.world.as_interior_mutable_readonly(),
154+
self.entity,
155+
self.location,
156+
)
157+
}
158+
fn as_interior_mutable(&mut self) -> InteriorMutableEntityRef<'_> {
159+
InteriorMutableEntityRef::new(self.world.as_interior_mutable(), self.entity, self.location)
160+
}
161+
185162
/// # Safety
186163
///
187164
/// - `entity` must be valid for `world`: the generation should match that of the entity at the same index.
@@ -237,50 +214,22 @@ impl<'w> EntityMut<'w> {
237214

238215
#[inline]
239216
pub fn get<T: Component>(&self) -> Option<&'_ T> {
240-
// SAFETY:
241-
// - entity location is valid
242-
// - world access is immutable, lifetime tied to `&self`
243-
// - the storage type provided is correct for T
244-
unsafe {
245-
self.world
246-
.get_component_with_type(
247-
TypeId::of::<T>(),
248-
T::Storage::STORAGE_TYPE,
249-
self.entity,
250-
self.location,
251-
)
252-
// SAFETY: returned component is of type T
253-
.map(|value| value.deref::<T>())
254-
}
217+
// SAFETY: &self implies shared access for duration of returned value
218+
unsafe { self.as_interior_mutable_readonly().get::<T>() }
255219
}
256220

257221
#[inline]
258222
pub fn get_mut<T: Component>(&mut self) -> Option<Mut<'_, T>> {
259-
let interior_mutable = InteriorMutableEntityRef::new(
260-
self.world.as_interior_mutable(),
261-
self.entity,
262-
self.location,
263-
);
264-
// SAFETY: interiormutableentityref has exclusive access
265-
unsafe { interior_mutable.get_mut() }
223+
// SAFETY: &mut self implies exclusive access for duration of returned value
224+
unsafe { self.as_interior_mutable().get_mut() }
266225
}
267226

268227
/// Retrieves the change ticks for the given component. This can be useful for implementing change
269228
/// detection in custom runtimes.
270229
#[inline]
271230
pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {
272-
// SAFETY:
273-
// - entity location is valid
274-
// - world access is immutable, lifetime tied to `&self`
275-
// - the storage type provided is correct for T
276-
unsafe {
277-
self.world.get_ticks_with_type(
278-
TypeId::of::<T>(),
279-
T::Storage::STORAGE_TYPE,
280-
self.entity,
281-
self.location,
282-
)
283-
}
231+
// SAFETY: &self implies shared access
232+
unsafe { self.as_interior_mutable_readonly().get_change_ticks::<T>() }
284233
}
285234

286235
/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
@@ -291,18 +240,10 @@ impl<'w> EntityMut<'w> {
291240
/// compile time.**
292241
#[inline]
293242
pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {
294-
let info = self.world.components().get_info(component_id)?;
295-
// SAFETY:
296-
// - entity location is valid
297-
// - world access is immutable, lifetime tied to `&self`
298-
// - the storage type provided is correct for T
243+
// SAFETY: &self implies shared access
299244
unsafe {
300-
self.world.get_ticks(
301-
component_id,
302-
info.storage_type(),
303-
self.entity,
304-
self.location,
305-
)
245+
self.as_interior_mutable_readonly()
246+
.get_change_ticks_by_id(component_id)
306247
}
307248
}
308249

0 commit comments

Comments
 (0)