Skip to content

Commit 7af25ca

Browse files
move get_component[_with_type], get_ticks[_with_type], get_component_and_ticks[_with_type] to Storages
1 parent dfb80ee commit 7af25ca

File tree

3 files changed

+295
-154
lines changed

3 files changed

+295
-154
lines changed

crates/bevy_ecs/src/storage/mod.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,187 @@ pub use resource::*;
99
pub use sparse_set::*;
1010
pub use table::*;
1111

12+
use crate::{
13+
archetype::Archetypes,
14+
component::{ComponentId, ComponentTicks, Components, StorageType},
15+
entity::{Entity, EntityLocation},
16+
};
17+
use bevy_ptr::Ptr;
18+
use std::{any::TypeId, cell::UnsafeCell};
19+
1220
/// The raw data stores of a [World](crate::world::World)
1321
#[derive(Default)]
1422
pub struct Storages {
1523
pub sparse_sets: SparseSets,
1624
pub tables: Tables,
1725
pub resources: Resources,
1826
}
27+
28+
impl Storages {
29+
/// Get a raw pointer to a particular [`Component`] and its [`ComponentTicks`] identified by their [`TypeId`]
30+
///
31+
/// # Safety
32+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
33+
/// - `component_id` must be valid
34+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
35+
/// - the caller must ensure that no aliasing rules are violated
36+
#[inline]
37+
pub unsafe fn get_component_and_ticks_with_type(
38+
&self,
39+
archetypes: &Archetypes,
40+
components: &Components,
41+
type_id: TypeId,
42+
entity: Entity,
43+
location: EntityLocation,
44+
) -> Option<(Ptr<'_>, &UnsafeCell<ComponentTicks>)> {
45+
let component_id = components.get_id(type_id)?;
46+
self.get_component_and_ticks(archetypes, components, component_id, entity, location)
47+
}
48+
49+
/// Get a raw pointer to a particular [`Component`] and its [`ComponentTicks`]
50+
///
51+
/// # Safety
52+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
53+
/// - `component_id` must be valid
54+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
55+
/// - the caller must ensure that no aliasing rules are violated
56+
#[inline]
57+
pub unsafe fn get_component_and_ticks(
58+
&self,
59+
archetypes: &Archetypes,
60+
components: &Components,
61+
component_id: ComponentId,
62+
entity: Entity,
63+
location: EntityLocation,
64+
) -> Option<(Ptr<'_>, &UnsafeCell<ComponentTicks>)> {
65+
let archetype = &archetypes[location.archetype_id];
66+
let component_info = unsafe { components.get_info_unchecked(component_id) };
67+
match component_info.storage_type() {
68+
StorageType::Table => {
69+
let table = &self.tables[archetype.table_id()];
70+
let components = table.get_column(component_id)?;
71+
let table_row = archetype.entity_table_row(location.index);
72+
// SAFETY: archetypes only store valid table_rows and the stored component type is T
73+
Some(unsafe {
74+
(
75+
components.get_data_unchecked(table_row),
76+
components.get_ticks_unchecked(table_row),
77+
)
78+
})
79+
}
80+
StorageType::SparseSet => self
81+
.sparse_sets
82+
.get(component_id)
83+
.and_then(|sparse_set| sparse_set.get_with_ticks(entity)),
84+
}
85+
}
86+
87+
/// Get a raw pointer to a particular [`Component`] on a particular [`Entity`], identified by the component's [`Type`]
88+
///
89+
/// # Safety
90+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
91+
/// the archetype
92+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
93+
/// - the caller must ensure that no aliasing rules are violated
94+
#[inline]
95+
pub unsafe fn get_component_with_type(
96+
&self,
97+
archetypes: &Archetypes,
98+
components: &Components,
99+
type_id: TypeId,
100+
entity: Entity,
101+
location: EntityLocation,
102+
) -> Option<Ptr<'_>> {
103+
let component_id = components.get_id(type_id)?;
104+
self.get_component(archetypes, components, component_id, entity, location)
105+
}
106+
107+
/// Get a raw pointer to a particular [`Component`] on a particular [`Entity`] in the provided [`World`].
108+
///
109+
/// # Safety
110+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
111+
/// the archetype
112+
/// - `component_id` must be valid
113+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
114+
/// - the caller must ensure that no aliasing rules are violated
115+
#[inline]
116+
pub unsafe fn get_component(
117+
&self,
118+
archetypes: &Archetypes,
119+
components: &Components,
120+
component_id: ComponentId,
121+
entity: Entity,
122+
location: EntityLocation,
123+
) -> Option<Ptr<'_>> {
124+
let archetype = &archetypes[location.archetype_id];
125+
// SAFETY: component_id exists and is therefore valid
126+
let component_info = unsafe { components.get_info_unchecked(component_id) };
127+
match component_info.storage_type() {
128+
StorageType::Table => {
129+
let table = &self.tables[archetype.table_id()];
130+
let components = table.get_column(component_id)?;
131+
let table_row = archetype.entity_table_row(location.index);
132+
// SAFETY: archetypes only store valid table_rows and the stored component type is T
133+
Some(unsafe { components.get_data_unchecked(table_row) })
134+
}
135+
StorageType::SparseSet => self
136+
.sparse_sets
137+
.get(component_id)
138+
.and_then(|sparse_set| sparse_set.get(entity)),
139+
}
140+
}
141+
142+
/// Get a raw pointer to the [`ComponentTicks`] on a particular [`Entity`], identified by the component's [`TypeId`]
143+
///
144+
/// # Safety
145+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
146+
/// the archetype
147+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
148+
/// - the caller must ensure that no aliasing rules are violated
149+
#[inline]
150+
pub unsafe fn get_ticks_with_type(
151+
&self,
152+
archetypes: &Archetypes,
153+
components: &Components,
154+
type_id: TypeId,
155+
entity: Entity,
156+
location: EntityLocation,
157+
) -> Option<&UnsafeCell<ComponentTicks>> {
158+
let component_id = components.get_id(type_id)?;
159+
self.get_ticks(archetypes, components, component_id, entity, location)
160+
}
161+
162+
/// Get a raw pointer to the [`ComponentTicks`] on a particular [`Entity`]
163+
///
164+
/// # Safety
165+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
166+
/// the archetype
167+
/// - `component_id` must be valid
168+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
169+
/// - the caller must ensure that no aliasing rules are violated
170+
#[inline]
171+
pub unsafe fn get_ticks(
172+
&self,
173+
archetypes: &Archetypes,
174+
components: &Components,
175+
component_id: ComponentId,
176+
entity: Entity,
177+
location: EntityLocation,
178+
) -> Option<&UnsafeCell<ComponentTicks>> {
179+
let archetype = &archetypes[location.archetype_id];
180+
let component_info = unsafe { components.get_info_unchecked(component_id) };
181+
match component_info.storage_type() {
182+
StorageType::Table => {
183+
let table = &self.tables[archetype.table_id()];
184+
let components = table.get_column(component_id)?;
185+
let table_row = archetype.entity_table_row(location.index);
186+
// SAFETY: archetypes only store valid table_rows and the stored component type is T
187+
Some(unsafe { components.get_ticks_unchecked(table_row) })
188+
}
189+
StorageType::SparseSet => self
190+
.sparse_sets
191+
.get(component_id)
192+
.and_then(|sparse_set| sparse_set.get_ticks(entity)),
193+
}
194+
}
195+
}

0 commit comments

Comments
 (0)