implement moving between blocks
authoralfadur
Mon, 26 Aug 2019 18:40:17 +0300
changeset 15362 135c29237a56
parent 15361 277acc9f9fcf
child 15363 b5e0a39856fd
implement moving between blocks
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<T: Clone>(&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::<T>() {
             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);
         }
     }