|
1 | 1 | use crate::{
|
2 | 2 | component::{ComponentId, ComponentInfo, ComponentTicks, Components},
|
3 | 3 | entity::Entity,
|
| 4 | + query::debug_checked_unreachable, |
4 | 5 | storage::{blob_vec::BlobVec, SparseSet},
|
5 | 6 | };
|
6 | 7 | use bevy_ptr::{OwningPtr, Ptr, PtrMut};
|
@@ -122,6 +123,30 @@ impl Column {
|
122 | 123 | (data, ticks)
|
123 | 124 | }
|
124 | 125 |
|
| 126 | + /// Removes the element from `other` at `src_row` and inserts it |
| 127 | + /// into the current column to initialize the values at `dst_row`. |
| 128 | + /// Does not do any bounds checking. |
| 129 | + /// |
| 130 | + /// # Safety |
| 131 | + /// |
| 132 | + /// - `other` must have the same data layout as `self` |
| 133 | + /// - `src_row` must be in bounds for `other` |
| 134 | + /// - `dst_row` must be in bounds for `self` |
| 135 | + /// - `other[src_row]` must be initialized to a valid value. |
| 136 | + /// - `self[dst_row]` must not be initalized yet. |
| 137 | + #[inline] |
| 138 | + pub(crate) unsafe fn initialize_from_unchecked( |
| 139 | + &mut self, |
| 140 | + other: &mut Column, |
| 141 | + src_row: usize, |
| 142 | + dst_row: usize, |
| 143 | + ) { |
| 144 | + debug_assert!(self.data.layout() == other.data.layout()); |
| 145 | + let ptr = self.data.get_unchecked_mut(dst_row); |
| 146 | + other.data.swap_remove_unchecked(src_row, ptr); |
| 147 | + *self.ticks.get_unchecked_mut(dst_row) = other.ticks.swap_remove(src_row); |
| 148 | + } |
| 149 | + |
125 | 150 | // # Safety
|
126 | 151 | // - ptr must point to valid data of this column's component type
|
127 | 152 | pub(crate) unsafe fn push(&mut self, ptr: OwningPtr<'_>, ticks: ComponentTicks) {
|
@@ -249,9 +274,11 @@ impl Table {
|
249 | 274 | let is_last = row == self.entities.len() - 1;
|
250 | 275 | let new_row = new_table.allocate(self.entities.swap_remove(row));
|
251 | 276 | for (component_id, column) in self.columns.iter_mut() {
|
252 |
| - let (data, ticks) = column.swap_remove_and_forget_unchecked(row); |
253 | 277 | if let Some(new_column) = new_table.get_column_mut(*component_id) {
|
254 |
| - new_column.initialize(new_row, data, ticks); |
| 278 | + new_column.initialize_from_unchecked(column, row, new_row); |
| 279 | + } else { |
| 280 | + // It's the caller's responsibility to drop these cases. |
| 281 | + let (_, _) = column.swap_remove_and_forget_unchecked(row); |
255 | 282 | }
|
256 | 283 | }
|
257 | 284 | TableMoveResult {
|
@@ -280,8 +307,7 @@ impl Table {
|
280 | 307 | let new_row = new_table.allocate(self.entities.swap_remove(row));
|
281 | 308 | for (component_id, column) in self.columns.iter_mut() {
|
282 | 309 | if let Some(new_column) = new_table.get_column_mut(*component_id) {
|
283 |
| - let (data, ticks) = column.swap_remove_and_forget_unchecked(row); |
284 |
| - new_column.initialize(new_row, data, ticks); |
| 310 | + new_column.initialize_from_unchecked(column, row, new_row); |
285 | 311 | } else {
|
286 | 312 | column.swap_remove_unchecked(row);
|
287 | 313 | }
|
@@ -311,9 +337,10 @@ impl Table {
|
311 | 337 | let is_last = row == self.entities.len() - 1;
|
312 | 338 | let new_row = new_table.allocate(self.entities.swap_remove(row));
|
313 | 339 | for (component_id, column) in self.columns.iter_mut() {
|
314 |
| - let new_column = new_table.get_column_mut(*component_id).unwrap(); |
315 |
| - let (data, ticks) = column.swap_remove_and_forget_unchecked(row); |
316 |
| - new_column.initialize(new_row, data, ticks); |
| 340 | + new_table |
| 341 | + .get_column_mut(*component_id) |
| 342 | + .unwrap_or_else(|| debug_checked_unreachable()) |
| 343 | + .initialize_from_unchecked(column, row, new_row); |
317 | 344 | }
|
318 | 345 | TableMoveResult {
|
319 | 346 | new_row,
|
|
0 commit comments