diff -r 8035f7452b48 -r bcd43b90401a rust/hwphysics/src/data.rs --- a/rust/hwphysics/src/data.rs Sun Mar 26 03:53:49 2023 +0300 +++ b/rust/hwphysics/src/data.rs Sun Mar 26 06:06:14 2023 +0300 @@ -224,6 +224,11 @@ } #[inline] + fn without_type(&self, type_bit: u64) -> Self { + Self::new(self.type_mask & !type_bit, self.tag_mask) + } + + #[inline] fn with_tag(&self, tag_bit: u64) -> Self { Self::new(self.type_mask, self.tag_mask | tag_bit) } @@ -273,7 +278,7 @@ debug_assert!(src_block_index != dest_block_index); let src_mask = self.block_masks[src_block_index as usize]; let dest_mask = self.block_masks[dest_block_index as usize]; - debug_assert!(src_mask.type_mask & dest_mask.type_mask == src_mask.type_mask); + debug_assert!(src_mask.type_mask & dest_mask.type_mask != 0); let src_block = &self.blocks[src_block_index as usize]; let dest_block = &self.blocks[dest_block_index as usize]; @@ -288,13 +293,17 @@ let size = self.element_sizes[i]; let src_ptr = src_block.component_blocks[i].unwrap().as_ptr(); - let dest_ptr = dest_block.component_blocks[i].unwrap().as_ptr(); + if let Some(dest_ptr) = dest_block.component_blocks[i] { + let dest_ptr = dest_ptr.as_ptr(); + unsafe { + copy_nonoverlapping( + src_ptr.add((src_index * size) as usize), + dest_ptr.add((dest_index * size) as usize), + size as usize, + ); + } + } unsafe { - copy_nonoverlapping( - src_ptr.add((src_index * size) as usize), - dest_ptr.add((dest_index * size) as usize), - size as usize, - ); if src_index < src_block.elements_count - 1 { copy_nonoverlapping( src_ptr.add((size * (src_block.elements_count - 1)) as usize), @@ -310,7 +319,7 @@ let src_block = &mut self.blocks[src_block_index as usize]; let gear_id = src_block.gear_ids()[src_index as usize]; - if src_index < src_block.elements_count - 1 { + if src_index + 1 < src_block.elements_count { let relocated_index = src_block.elements_count as usize - 1; let gear_ids = src_block.gear_ids_mut(); let relocated_id = gear_ids[relocated_index]; @@ -470,16 +479,24 @@ pub fn remove(&mut self, gear_id: GearId) { if let Some(type_index) = self.get_type_index::() { + let type_bit = 1 << type_index as u64; let entry = self.lookup[gear_id.get() as usize - 1]; + if let Some(index) = entry.index { - let mut dest_mask = self.block_masks[entry.block_index as usize]; - dest_mask.type_mask &= !(1 << type_index as u64); + let mask = self.block_masks[entry.block_index as usize]; + let new_mask = mask.without_type(type_bit); - if dest_mask.type_mask == 0 { - self.remove_from_block(entry.block_index, index.get() - 1); - } else { - let dest_block_index = self.ensure_block(dest_mask); - self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); + if new_mask != mask { + if new_mask.type_mask == 0 { + self.remove_from_block(entry.block_index, index.get() - 1); + } else { + let dest_block_index = self.ensure_block(new_mask); + self.move_between_blocks( + entry.block_index, + index.get() - 1, + dest_block_index, + ); + } } } } else { @@ -629,7 +646,12 @@ use super::{super::common::GearId, GearDataManager}; #[derive(Clone)] - struct Datum { + struct DatumA { + value: u32, + } + + #[derive(Clone)] + struct DatumB { value: u32, } @@ -639,15 +661,15 @@ #[test] fn direct_access() { let mut manager = GearDataManager::new(); - manager.register::(); + manager.register::(); for i in 1..=5 { - manager.add(GearId::new(i as u16).unwrap(), &Datum { value: i * i }); + manager.add(GearId::new(i as u16).unwrap(), &DatumA { value: i * i }); } for i in 1..=5 { assert_eq!( manager - .get::(GearId::new(i as u16).unwrap()) + .get::(GearId::new(i as u16).unwrap()) .unwrap() .value, i * i @@ -658,46 +680,72 @@ #[test] fn single_component_iteration() { let mut manager = GearDataManager::new(); - manager.register::(); + manager.register::(); + for i in 1..=5 { - manager.add(GearId::new(i as u16).unwrap(), &Datum { value: i }); + manager.add(GearId::new(i as u16).unwrap(), &DatumA { value: i }); } let mut sum = 0; - manager.iter().run(|(d,): (&Datum,)| sum += d.value); + manager.iter().run(|(d,): (&DatumA,)| sum += d.value); assert_eq!(sum, 15); - manager.iter().run(|(d,): (&mut Datum,)| d.value += 1); - manager.iter().run(|(d,): (&Datum,)| sum += d.value); + manager.iter().run(|(d,): (&mut DatumA,)| d.value += 1); + manager.iter().run(|(d,): (&DatumA,)| sum += d.value); assert_eq!(sum, 35); } #[test] fn tagged_component_iteration() { let mut manager = GearDataManager::new(); - manager.register::(); + manager.register::(); manager.register::(); - for i in 1..=10 { - let gear_id = GearId::new(i as u16).unwrap(); - manager.add(gear_id, &Datum { value: i }); - } for i in 1..=10 { let gear_id = GearId::new(i as u16).unwrap(); - if i & 1 == 0 { - manager.add_tag::(gear_id); - } + manager.add(gear_id, &DatumA { value: i }); + } + + for i in (2..=10).step_by(2) { + let gear_id = GearId::new(i as u16).unwrap(); + manager.add_tag::(gear_id); } let mut sum = 0; - manager.iter().run(|(d,): (&Datum,)| sum += d.value); + manager.iter().run(|(d,): (&DatumA,)| sum += d.value); assert_eq!(sum, 55); let mut tag_sum = 0; manager .iter() .with_tags::<&Tag>() - .run(|(d,): (&Datum,)| tag_sum += d.value); + .run(|(d,): (&DatumA,)| tag_sum += d.value); assert_eq!(tag_sum, 30); } + + #[test] + fn removal() { + let mut manager = GearDataManager::new(); + manager.register::(); + manager.register::(); + + for i in 1..=10 { + let gear_id = GearId::new(i as u16).unwrap(); + manager.add(gear_id, &DatumA { value: i }); + manager.add(gear_id, &DatumB { value: i }); + } + + for i in (1..=10).step_by(2) { + let gear_id = GearId::new(i as u16).unwrap(); + manager.remove::(gear_id); + } + + let mut sum_a = 0; + manager.iter().run(|(d,): (&DatumA,)| sum_a += d.value); + assert_eq!(sum_a, 30); + + let mut sum_b = 0; + manager.iter().run(|(d,): (&DatumB,)| sum_b += d.value); + assert_eq!(sum_b, 55); + } }