diff -r 277acc9f9fcf -r 135c29237a56 rust/hwphysics/src/data.rs --- a/rust/hwphysics/src/data.rs Mon Aug 26 17:32:43 2019 +0300 +++ b/rust/hwphysics/src/data.rs Mon Aug 26 18:40:17 2019 +0300 @@ -3,7 +3,7 @@ any::TypeId, mem::{size_of, MaybeUninit}, num::NonZeroU16, - ptr::NonNull, + ptr::{copy_nonoverlapping, NonNull}, slice, }; @@ -57,7 +57,7 @@ let max_elements = (BLOCK_SIZE / total_size as usize) as u16; let mut data: Box<[u8; BLOCK_SIZE]> = - Box::new(unsafe { std::mem::MaybeUninit::uninit().assume_init() }); + Box::new(unsafe { MaybeUninit::uninit().assume_init() }); let mut blocks = [None; 64]; let mut offset = 0; @@ -112,15 +112,29 @@ } fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) { + debug_assert!(from_block_index != to_block_index); let source_mask = self.block_masks[from_block_index as usize]; let destination_mask = self.block_masks[to_block_index as usize]; debug_assert!(source_mask & destination_mask == source_mask); let source = &self.blocks[from_block_index as usize]; let destination = &self.blocks[to_block_index as usize]; + debug_assert!(from_index < source.elements_count); + debug_assert!(!destination.is_full()); + for i in 0..64 { - unimplemented!() + if source_mask & 1u64 << i != 0 { + unsafe { + copy_nonoverlapping( + source.blocks[i].unwrap().as_ptr(), + destination.blocks[i].unwrap().as_ptr(), + self.element_sizes[i] as usize, + ); + } + } } + self.blocks[from_block_index as usize].elements_count -= 1; + self.blocks[to_block_index as usize].elements_count += 1; } fn add_to_block(&mut self, block_index: u16, value: &T) { @@ -145,9 +159,9 @@ for (i, size) in self.element_sizes.iter().cloned().enumerate() { if index < block.elements_count - 1 { - if let Some(mut ptr) = block.blocks[i] { + if let Some(ptr) = block.blocks[i] { unsafe { - std::ptr::copy_nonoverlapping( + copy_nonoverlapping( ptr.as_ptr() .add((size * (block.elements_count - 1)) as usize), ptr.as_ptr().add((size * index) as usize), @@ -201,8 +215,29 @@ if let Some(type_index) = self.get_type_index::() { let entry = self.lookup[gear_id.get() as usize - 1]; if let Some(index) = entry.index { - self.remove_from_block(entry.block_index, index.get() - 1); + let destination_mask = + self.block_masks[entry.block_index as usize] & !(1u64 << type_index as u64); + + if destination_mask == 0 { + self.remove_all(gear_id) + } else { + let destination_block_index = self.ensure_group(destination_mask); + self.move_between_blocks( + entry.block_index, + index.get() - 1, + destination_block_index, + ); + } } + } else { + panic!("Unregistered type") + } + } + + pub fn remove_all(&mut self, gear_id: GearId) { + let entry = self.lookup[gear_id.get() as usize - 1]; + if let Some(index) = entry.index { + self.remove_from_block(entry.block_index, index.get() - 1); } }