1 use super::common::GearId; |
1 use super::common::GearId; |
2 use std::{ |
2 use std::{ |
3 any::TypeId, |
3 any::TypeId, |
4 mem::{size_of, MaybeUninit}, |
4 mem::{size_of, MaybeUninit}, |
5 num::NonZeroU16, |
5 num::NonZeroU16, |
6 ptr::{copy_nonoverlapping, NonNull}, |
6 ptr::{copy_nonoverlapping, NonNull, null_mut}, |
7 slice, |
7 slice, |
8 }; |
8 }; |
9 |
9 |
10 pub unsafe trait TypeTuple: Sized { |
10 pub unsafe trait TypeTuple: Sized { |
11 fn len() -> usize; |
11 fn len() -> usize; |
12 fn get_types(dest: &mut Vec<TypeId>); |
12 fn get_types(dest: &mut Vec<TypeId>); |
13 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, mut f: F) |
13 unsafe fn iter<F>(slices: &[*mut u8], count: usize, mut f: F) |
14 where |
14 where |
15 F: FnMut(Self); |
15 F: FnMut(Self); |
16 } |
16 } |
17 |
17 |
18 unsafe impl<T: 'static> TypeTuple for (&T,) { |
18 unsafe impl<T: 'static> TypeTuple for (&T,) { |
22 |
22 |
23 fn get_types(dest: &mut Vec<TypeId>) { |
23 fn get_types(dest: &mut Vec<TypeId>) { |
24 dest.push(TypeId::of::<T>()); |
24 dest.push(TypeId::of::<T>()); |
25 } |
25 } |
26 |
26 |
27 unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, mut f: F) |
27 unsafe fn iter<F>(slices: &[*mut u8], count: usize, mut f: F) |
28 where |
28 where |
29 F: FnMut(Self), |
29 F: FnMut(Self), |
30 { |
30 { |
31 let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count); |
31 let slice1 = slice::from_raw_parts(slices[0] as *const T, count); |
32 for i in 0..count { |
32 for i in 0..count { |
33 f((slice1.get_unchecked(i),)); |
33 f((slice1.get_unchecked(i),)); |
34 } |
34 } |
35 } |
35 } |
36 } |
36 } |
252 self.element_sizes[self.types.len()] = size_of::<T>() as u16; |
252 self.element_sizes[self.types.len()] = size_of::<T>() as u16; |
253 self.types.push(id); |
253 self.types.push(id); |
254 } |
254 } |
255 } |
255 } |
256 |
256 |
257 fn create_selector(&self, types: &[TypeId]) -> u64 { |
|
258 let mut selector = 0; |
|
259 for (i, typ) in self.types.iter().enumerate() { |
|
260 if types.contains(&typ) { |
|
261 selector |= 1 << (i as u64) |
|
262 } |
|
263 } |
|
264 selector |
|
265 } |
|
266 |
|
267 pub fn iter<T: TypeTuple + 'static, F: FnMut(T)>(&self, mut f: F) { |
257 pub fn iter<T: TypeTuple + 'static, F: FnMut(T)>(&self, mut f: F) { |
268 let mut types = vec![]; |
258 let mut arg_types = Vec::with_capacity(64); |
269 T::get_types(&mut types); |
259 T::get_types(&mut arg_types); |
270 debug_assert!(types.iter().all(|t| self.types.contains(t))); |
260 |
271 |
261 let mut type_indices = vec![-1i8; arg_types.len()]; |
272 let types_count = types.len(); |
262 let mut selector = 0u64; |
273 let selector = self.create_selector(&types); |
263 |
274 |
264 for (arg_index, type_id) in arg_types.iter().enumerate() { |
275 let mut slices = Vec::with_capacity(64); |
265 match self.types.iter().position(|t| t == type_id) { |
|
266 Some(i) if selector & 1 << i as u64 != 0 => panic!("Duplicate type"), |
|
267 Some(i) => { |
|
268 type_indices[arg_index] = i as i8; |
|
269 selector &= 1 << i as u64; |
|
270 }, |
|
271 None => panic!("Unregistered type") |
|
272 } |
|
273 } |
|
274 |
|
275 let mut slices = vec![null_mut(); arg_types.len()]; |
276 |
276 |
277 for (block_index, mask) in self.block_masks.iter().enumerate() { |
277 for (block_index, mask) in self.block_masks.iter().enumerate() { |
278 if mask & selector == selector { |
278 if mask & selector == selector { |
279 slices.clear(); |
|
280 let block = &self.blocks[block_index]; |
279 let block = &self.blocks[block_index]; |
281 |
280 |
282 for (i, ptr_opt) in block.component_blocks.iter().cloned().enumerate() { |
281 for (arg_index, type_index) in type_indices.iter().cloned().enumerate() { |
283 if let Some(ptr) = ptr_opt { |
282 slices[arg_index as usize] = |
284 slices.push(ptr); |
283 block.component_blocks[type_index as usize].unwrap().as_ptr() |
285 } |
|
286 } |
284 } |
287 |
285 |
288 unsafe { |
286 unsafe { |
289 T::iter(&slices[..], block.elements_count as usize, |x| f(x)); |
287 T::iter(&slices[..], block.elements_count as usize, |x| f(x)); |
290 } |
288 } |