rust/hwphysics/src/data.rs
changeset 15362 135c29237a56
parent 15361 277acc9f9fcf
child 15363 b5e0a39856fd
equal deleted inserted replaced
15361:277acc9f9fcf 15362:135c29237a56
     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::NonNull,
     6     ptr::{copy_nonoverlapping, NonNull},
     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;
    55             .map(|(_, size)| *size)
    55             .map(|(_, size)| *size)
    56             .sum();
    56             .sum();
    57         let max_elements = (BLOCK_SIZE / total_size as usize) as u16;
    57         let max_elements = (BLOCK_SIZE / total_size as usize) as u16;
    58 
    58 
    59         let mut data: Box<[u8; BLOCK_SIZE]> =
    59         let mut data: Box<[u8; BLOCK_SIZE]> =
    60             Box::new(unsafe { std::mem::MaybeUninit::uninit().assume_init() });
    60             Box::new(unsafe { MaybeUninit::uninit().assume_init() });
    61         let mut blocks = [None; 64];
    61         let mut blocks = [None; 64];
    62         let mut offset = 0;
    62         let mut offset = 0;
    63 
    63 
    64         for i in 0..64 {
    64         for i in 0..64 {
    65             if mask & (164 << i) != 0 {
    65             if mask & (164 << i) != 0 {
   110         let type_id = TypeId::of::<T>();
   110         let type_id = TypeId::of::<T>();
   111         self.types.iter().position(|id| *id == type_id)
   111         self.types.iter().position(|id| *id == type_id)
   112     }
   112     }
   113 
   113 
   114     fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) {
   114     fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) {
       
   115         debug_assert!(from_block_index != to_block_index);
   115         let source_mask = self.block_masks[from_block_index as usize];
   116         let source_mask = self.block_masks[from_block_index as usize];
   116         let destination_mask = self.block_masks[to_block_index as usize];
   117         let destination_mask = self.block_masks[to_block_index as usize];
   117         debug_assert!(source_mask & destination_mask == source_mask);
   118         debug_assert!(source_mask & destination_mask == source_mask);
   118 
   119 
   119         let source = &self.blocks[from_block_index as usize];
   120         let source = &self.blocks[from_block_index as usize];
   120         let destination = &self.blocks[to_block_index as usize];
   121         let destination = &self.blocks[to_block_index as usize];
       
   122         debug_assert!(from_index < source.elements_count);
       
   123         debug_assert!(!destination.is_full());
       
   124 
   121         for i in 0..64 {
   125         for i in 0..64 {
   122             unimplemented!()
   126             if source_mask & 1u64 << i != 0 {
   123         }
   127                 unsafe {
       
   128                     copy_nonoverlapping(
       
   129                         source.blocks[i].unwrap().as_ptr(),
       
   130                         destination.blocks[i].unwrap().as_ptr(),
       
   131                         self.element_sizes[i] as usize,
       
   132                     );
       
   133                 }
       
   134             }
       
   135         }
       
   136         self.blocks[from_block_index as usize].elements_count -= 1;
       
   137         self.blocks[to_block_index as usize].elements_count += 1;
   124     }
   138     }
   125 
   139 
   126     fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) {
   140     fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) {
   127         debug_assert!(self.block_masks[block_index as usize].count_ones() == 1);
   141         debug_assert!(self.block_masks[block_index as usize].count_ones() == 1);
   128 
   142 
   143         let block = &mut self.blocks[block_index as usize];
   157         let block = &mut self.blocks[block_index as usize];
   144         debug_assert!(index < block.elements_count);
   158         debug_assert!(index < block.elements_count);
   145 
   159 
   146         for (i, size) in self.element_sizes.iter().cloned().enumerate() {
   160         for (i, size) in self.element_sizes.iter().cloned().enumerate() {
   147             if index < block.elements_count - 1 {
   161             if index < block.elements_count - 1 {
   148                 if let Some(mut ptr) = block.blocks[i] {
   162                 if let Some(ptr) = block.blocks[i] {
   149                     unsafe {
   163                     unsafe {
   150                         std::ptr::copy_nonoverlapping(
   164                         copy_nonoverlapping(
   151                             ptr.as_ptr()
   165                             ptr.as_ptr()
   152                                 .add((size * (block.elements_count - 1)) as usize),
   166                                 .add((size * (block.elements_count - 1)) as usize),
   153                             ptr.as_ptr().add((size * index) as usize),
   167                             ptr.as_ptr().add((size * index) as usize),
   154                             size as usize,
   168                             size as usize,
   155                         );
   169                         );
   199 
   213 
   200     pub fn remove<T: 'static>(&mut self, gear_id: GearId) {
   214     pub fn remove<T: 'static>(&mut self, gear_id: GearId) {
   201         if let Some(type_index) = self.get_type_index::<T>() {
   215         if let Some(type_index) = self.get_type_index::<T>() {
   202             let entry = self.lookup[gear_id.get() as usize - 1];
   216             let entry = self.lookup[gear_id.get() as usize - 1];
   203             if let Some(index) = entry.index {
   217             if let Some(index) = entry.index {
   204                 self.remove_from_block(entry.block_index, index.get() - 1);
   218                 let destination_mask =
   205             }
   219                     self.block_masks[entry.block_index as usize] & !(1u64 << type_index as u64);
       
   220 
       
   221                 if destination_mask == 0 {
       
   222                     self.remove_all(gear_id)
       
   223                 } else {
       
   224                     let destination_block_index = self.ensure_group(destination_mask);
       
   225                     self.move_between_blocks(
       
   226                         entry.block_index,
       
   227                         index.get() - 1,
       
   228                         destination_block_index,
       
   229                     );
       
   230                 }
       
   231             }
       
   232         } else {
       
   233             panic!("Unregistered type")
       
   234         }
       
   235     }
       
   236 
       
   237     pub fn remove_all(&mut self, gear_id: GearId) {
       
   238         let entry = self.lookup[gear_id.get() as usize - 1];
       
   239         if let Some(index) = entry.index {
       
   240             self.remove_from_block(entry.block_index, index.get() - 1);
   206         }
   241         }
   207     }
   242     }
   208 
   243 
   209     pub fn register<T: 'static>(&mut self) {
   244     pub fn register<T: 'static>(&mut self) {
   210         debug_assert!(!std::mem::needs_drop::<T>());
   245         debug_assert!(!std::mem::needs_drop::<T>());