implement addition to/removal from blocks
authoralfadur
Mon, 26 Aug 2019 17:32:43 +0300
changeset 15361 277acc9f9fcf
parent 15360 09fc16926855
child 15362 135c29237a56
implement addition to/removal from blocks
rust/hwphysics/src/data.rs
--- a/rust/hwphysics/src/data.rs	Mon Aug 26 12:36:07 2019 +0200
+++ b/rust/hwphysics/src/data.rs	Mon Aug 26 17:32:43 2019 +0300
@@ -7,7 +7,7 @@
     slice,
 };
 
-pub trait TypeTuple: Sized {
+pub unsafe trait TypeTuple: Sized {
     fn len() -> usize;
     fn get_types(dest: &mut Vec<TypeId>);
     unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F)
@@ -15,7 +15,7 @@
         F: Fn(Self);
 }
 
-impl<T: 'static> TypeTuple for (&T,) {
+unsafe impl<T: 'static> TypeTuple for (&T,) {
     fn len() -> usize {
         1
     }
@@ -123,12 +123,41 @@
         }
     }
 
-    fn add_to_block<T>(&mut self, block_index: u16, value: &T) {
-        unimplemented!()
+    fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) {
+        debug_assert!(self.block_masks[block_index as usize].count_ones() == 1);
+
+        let block = &mut self.blocks[block_index as usize];
+        debug_assert!(block.elements_count < block.max_elements);
+
+        unsafe {
+            let slice = slice::from_raw_parts_mut(
+                block.data.as_mut_ptr() as *mut T,
+                block.max_elements as usize,
+            );
+            *slice.get_unchecked_mut(block.elements_count as usize) = value.clone();
+        };
+        block.elements_count += 1;
     }
 
     fn remove_from_block(&mut self, block_index: u16, index: u16) {
-        unimplemented!()
+        let block = &mut self.blocks[block_index as usize];
+        debug_assert!(index < block.elements_count);
+
+        for (i, size) in self.element_sizes.iter().cloned().enumerate() {
+            if index < block.elements_count - 1 {
+                if let Some(mut ptr) = block.blocks[i] {
+                    unsafe {
+                        std::ptr::copy_nonoverlapping(
+                            ptr.as_ptr()
+                                .add((size * (block.elements_count - 1)) as usize),
+                            ptr.as_ptr().add((size * index) as usize),
+                            size as usize,
+                        );
+                    }
+                }
+            }
+        }
+        block.elements_count -= 1;
     }
 
     #[inline]
@@ -178,9 +207,9 @@
     }
 
     pub fn register<T: 'static>(&mut self) {
-        assert!(!std::mem::needs_drop::<T>());
-        assert!(self.types.len() <= 64);
-        assert!(size_of::<T>() <= u16::max_value() as usize);
+        debug_assert!(!std::mem::needs_drop::<T>());
+        debug_assert!(self.types.len() <= 64);
+        debug_assert!(size_of::<T>() <= u16::max_value() as usize);
 
         let id = TypeId::of::<T>();
         if !self.types.contains(&id) {
@@ -202,14 +231,18 @@
     pub fn iter<T: TypeTuple + 'static, F: Fn(T) + Copy>(&self, f: F) {
         let mut types = vec![];
         T::get_types(&mut types);
-        let types_count = types.len();
+        debug_assert!(types.iter().all(|t| self.types.contains(t)));
 
+        let types_count = types.len();
         let selector = self.create_selector(&types);
+
         for (block_index, mask) in self.block_masks.iter().enumerate() {
             if mask & selector == selector {
                 let block = &self.blocks[block_index];
                 for element_index in 0..block.max_elements {
-                    unimplemented!()
+                    unsafe {
+                        T::iter(unimplemented!(), block.elements_count as usize, f);
+                    }
                 }
             }
         }