Skip to content

Commit ae2172e

Browse files
move get_component[_with_type], get_ticks[_with_type], get_component_and_ticks[_with_type] to Storages
1 parent feac2c2 commit ae2172e

File tree

3 files changed

+313
-259
lines changed

3 files changed

+313
-259
lines changed

crates/bevy_ecs/src/storage/mod.rs

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ 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, TickCells},
15+
entity::{Entity, EntityLocation},
16+
};
17+
use bevy_ptr::Ptr;
18+
use std::any::TypeId;
19+
1220
/// The raw data stores of a [World](crate::world::World)
1321
#[derive(Default)]
1422
pub struct Storages {
@@ -17,3 +25,182 @@ pub struct Storages {
1725
pub resources: Resources<true>,
1826
pub non_send_resources: Resources<false>,
1927
}
28+
29+
impl Storages {
30+
/// Get a raw pointer to a particular [`Component`] and its [`ComponentTicks`] identified by their [`TypeId`]
31+
///
32+
/// # Safety
33+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
34+
/// - `component_id` must be valid
35+
/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
36+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
37+
/// - the caller must ensure that no aliasing rules are violated
38+
#[inline]
39+
pub unsafe fn get_component_and_ticks_with_type(
40+
&self,
41+
archetypes: &Archetypes,
42+
components: &Components,
43+
type_id: TypeId,
44+
storage_type: StorageType,
45+
entity: Entity,
46+
location: EntityLocation,
47+
) -> Option<(Ptr<'_>, TickCells<'_>)> {
48+
let component_id = components.get_id(type_id)?;
49+
self.get_component_and_ticks(archetypes, component_id, storage_type, entity, location)
50+
}
51+
52+
/// Get a raw pointer to a particular [`Component`] and its [`ComponentTicks`]
53+
///
54+
/// # Safety
55+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
56+
/// - `component_id` must be valid
57+
/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
58+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
59+
/// - the caller must ensure that no aliasing rules are violated
60+
#[inline]
61+
pub unsafe fn get_component_and_ticks(
62+
&self,
63+
archetypes: &Archetypes,
64+
component_id: ComponentId,
65+
storage_type: StorageType,
66+
entity: Entity,
67+
location: EntityLocation,
68+
) -> Option<(Ptr<'_>, TickCells<'_>)> {
69+
match storage_type {
70+
StorageType::Table => {
71+
let (components, table_row) =
72+
fetch_table(archetypes, self, location, component_id)?;
73+
74+
// SAFETY: archetypes only store valid table_rows and the stored component type is T
75+
Some((
76+
components.get_data_unchecked(table_row),
77+
TickCells {
78+
added: components.get_added_ticks_unchecked(table_row),
79+
changed: components.get_changed_ticks_unchecked(table_row),
80+
},
81+
))
82+
}
83+
StorageType::SparseSet => fetch_sparse_set(self, component_id)?.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+
storage_type: StorageType,
101+
entity: Entity,
102+
location: EntityLocation,
103+
) -> Option<Ptr<'_>> {
104+
let component_id = components.get_id(type_id)?;
105+
self.get_component(archetypes, component_id, storage_type, entity, location)
106+
}
107+
108+
/// Get a raw pointer to a particular [`Component`] on a particular [`Entity`] in the provided [`World`].
109+
///
110+
/// # Safety
111+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
112+
/// the archetype
113+
/// - `component_id`
114+
/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
115+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
116+
/// - the caller must ensure that no aliasing rules are violated
117+
#[inline]
118+
pub unsafe fn get_component(
119+
&self,
120+
archetypes: &Archetypes,
121+
component_id: ComponentId,
122+
storage_type: StorageType,
123+
entity: Entity,
124+
location: EntityLocation,
125+
) -> Option<Ptr<'_>> {
126+
// SAFETY: component_id exists and is therefore valid
127+
match storage_type {
128+
StorageType::Table => {
129+
let (components, table_row) =
130+
fetch_table(archetypes, self, location, component_id)?;
131+
// SAFETY: archetypes only store valid table_rows and the stored component type is T
132+
Some(components.get_data_unchecked(table_row))
133+
}
134+
StorageType::SparseSet => fetch_sparse_set(self, component_id)?.get(entity),
135+
}
136+
}
137+
138+
/// Get a raw pointer to the [`ComponentTicks`] on a particular [`Entity`], identified by the component's [`TypeId`]
139+
///
140+
/// # Safety
141+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
142+
/// the archetype
143+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
144+
/// - the caller must ensure that no aliasing rules are violated
145+
#[inline]
146+
pub unsafe fn get_ticks_with_type(
147+
&self,
148+
archetypes: &Archetypes,
149+
components: &Components,
150+
type_id: TypeId,
151+
storage_type: StorageType,
152+
entity: Entity,
153+
location: EntityLocation,
154+
) -> Option<ComponentTicks> {
155+
let component_id = components.get_id(type_id)?;
156+
self.get_ticks(archetypes, component_id, storage_type, entity, location)
157+
}
158+
159+
/// Get a raw pointer to the [`ComponentTicks`] on a particular [`Entity`]
160+
///
161+
/// # Safety
162+
/// - `entity_location` must be within bounds of the given archetype and `entity` must exist inside
163+
/// the archetype
164+
/// - `component_id` must be valid
165+
/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
166+
/// - `Archetypes` and `Components` must come from the world this of this `Storages`
167+
/// - the caller must ensure that no aliasing rules are violated
168+
#[inline]
169+
pub unsafe fn get_ticks(
170+
&self,
171+
archetypes: &Archetypes,
172+
component_id: ComponentId,
173+
storage_type: StorageType,
174+
entity: Entity,
175+
location: EntityLocation,
176+
) -> Option<ComponentTicks> {
177+
match storage_type {
178+
StorageType::Table => {
179+
let (components, table_row) =
180+
fetch_table(archetypes, self, location, component_id)?;
181+
// SAFETY: archetypes only store valid table_rows and the stored component type is T
182+
Some(components.get_ticks_unchecked(table_row))
183+
}
184+
StorageType::SparseSet => fetch_sparse_set(self, component_id)?.get_ticks(entity),
185+
}
186+
}
187+
}
188+
189+
#[inline]
190+
unsafe fn fetch_table<'s>(
191+
archetypes: &Archetypes,
192+
storages: &'s Storages,
193+
location: EntityLocation,
194+
component_id: ComponentId,
195+
) -> Option<(&'s Column, TableRow)> {
196+
let archetype = &archetypes[location.archetype_id];
197+
let table = &storages.tables[archetype.table_id()];
198+
let components = table.get_column(component_id)?;
199+
let table_row = archetype.entity_table_row(location.archetype_row);
200+
Some((components, table_row))
201+
}
202+
203+
#[inline]
204+
fn fetch_sparse_set(storages: &Storages, component_id: ComponentId) -> Option<&ComponentSparseSet> {
205+
storages.sparse_sets.get(component_id)
206+
}

0 commit comments

Comments
 (0)