make sure component slice order corresponds to the type args
authoralfadur
Tue, 27 Aug 2019 20:09:17 +0300
changeset 15367 d6b4586b271f
parent 15366 381c828865e7
child 15368 445138f388d4
make sure component slice order corresponds to the type args
rust/hwphysics/src/data.rs
--- a/rust/hwphysics/src/data.rs	Tue Aug 27 14:37:39 2019 +0200
+++ b/rust/hwphysics/src/data.rs	Tue Aug 27 20:09:17 2019 +0300
@@ -3,14 +3,14 @@
     any::TypeId,
     mem::{size_of, MaybeUninit},
     num::NonZeroU16,
-    ptr::{copy_nonoverlapping, NonNull},
+    ptr::{copy_nonoverlapping, NonNull, null_mut},
     slice,
 };
 
 pub unsafe trait TypeTuple: Sized {
     fn len() -> usize;
     fn get_types(dest: &mut Vec<TypeId>);
-    unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, mut f: F)
+    unsafe fn iter<F>(slices: &[*mut u8], count: usize, mut f: F)
     where
         F: FnMut(Self);
 }
@@ -24,11 +24,11 @@
         dest.push(TypeId::of::<T>());
     }
 
-    unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, mut f: F)
+    unsafe fn iter<F>(slices: &[*mut u8], count: usize, mut f: F)
     where
         F: FnMut(Self),
     {
-        let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count);
+        let slice1 = slice::from_raw_parts(slices[0] as *const T, count);
         for i in 0..count {
             f((slice1.get_unchecked(i),));
         }
@@ -254,35 +254,33 @@
         }
     }
 
-    fn create_selector(&self, types: &[TypeId]) -> u64 {
-        let mut selector = 0;
-        for (i, typ) in self.types.iter().enumerate() {
-            if types.contains(&typ) {
-                selector |= 1 << (i as u64)
+    pub fn iter<T: TypeTuple + 'static, F: FnMut(T)>(&self, mut f: F) {
+        let mut arg_types = Vec::with_capacity(64);
+        T::get_types(&mut arg_types);
+
+        let mut type_indices = vec![-1i8; arg_types.len()];
+        let mut selector = 0u64;
+
+        for (arg_index, type_id) in arg_types.iter().enumerate() {
+            match self.types.iter().position(|t| t == type_id) {
+                Some(i) if selector & 1 << i as u64 != 0 => panic!("Duplicate type"),
+                Some(i) => {
+                    type_indices[arg_index] = i as i8;
+                    selector &= 1 << i as u64;
+                },
+                None => panic!("Unregistered type")
             }
         }
-        selector
-    }
 
-    pub fn iter<T: TypeTuple + 'static, F: FnMut(T)>(&self, mut f: F) {
-        let mut types = vec![];
-        T::get_types(&mut types);
-        debug_assert!(types.iter().all(|t| self.types.contains(t)));
-
-        let types_count = types.len();
-        let selector = self.create_selector(&types);
-
-        let mut slices = Vec::with_capacity(64);
+        let mut slices = vec![null_mut(); arg_types.len()];
 
         for (block_index, mask) in self.block_masks.iter().enumerate() {
             if mask & selector == selector {
-                slices.clear();
                 let block = &self.blocks[block_index];
 
-                for (i, ptr_opt) in block.component_blocks.iter().cloned().enumerate() {
-                    if let Some(ptr) = ptr_opt {
-                        slices.push(ptr);
-                    }
+                for (arg_index, type_index) in type_indices.iter().cloned().enumerate() {
+                    slices[arg_index as usize] =
+                        block.component_blocks[type_index as usize].unwrap().as_ptr()
                 }
 
                 unsafe {