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