rust/hwphysics/src/data.rs
author alfadur
Mon, 26 Aug 2019 17:32:43 +0300
changeset 15356 277acc9f9fcf
parent 15354 dff37ac61dcf
child 15357 135c29237a56
permissions -rw-r--r--
implement addition to/removal from blocks
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     1
use super::common::GearId;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     2
use std::{
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     3
    any::TypeId,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     4
    mem::{size_of, MaybeUninit},
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     5
    num::NonZeroU16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     6
    ptr::NonNull,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     7
    slice,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     8
};
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
     9
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
    10
pub unsafe trait TypeTuple: Sized {
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    11
    fn len() -> usize;
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    12
    fn get_types(dest: &mut Vec<TypeId>);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    13
    unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    14
    where
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    15
        F: Fn(Self);
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    16
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    17
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
    18
unsafe impl<T: 'static> TypeTuple for (&T,) {
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    19
    fn len() -> usize {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    20
        1
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    21
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    22
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    23
    fn get_types(dest: &mut Vec<TypeId>) {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    24
        dest.push(TypeId::of::<T>());
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    25
    }
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    26
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    27
    unsafe fn iter<F>(slices: &[NonNull<u8>], count: usize, f: F)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    28
    where
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    29
        F: Fn(Self),
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    30
    {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    31
        let slice1 = slice::from_raw_parts(slices[0].as_ptr() as *const T, count);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    32
        for i in 0..count {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    33
            f((slice1.get_unchecked(i),));
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    34
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    35
    }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    36
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    37
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    38
const BLOCK_SIZE: usize = 32768;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    39
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    40
struct DataBlock {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    41
    max_elements: u16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    42
    elements_count: u16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    43
    data: Box<[u8; BLOCK_SIZE]>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    44
    blocks: [Option<NonNull<u8>>; 64],
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    45
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    46
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    47
impl Unpin for DataBlock {}
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    48
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    49
impl DataBlock {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    50
    fn new(mask: u64, element_sizes: &[u16; 64]) -> Self {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    51
        let total_size: u16 = element_sizes
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    52
            .iter()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    53
            .enumerate()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    54
            .filter(|(i, _)| mask & (164 << *i as u64) != 0)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    55
            .map(|(_, size)| *size)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    56
            .sum();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    57
        let max_elements = (BLOCK_SIZE / total_size as usize) as u16;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    58
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    59
        let mut data: Box<[u8; BLOCK_SIZE]> =
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    60
            Box::new(unsafe { std::mem::MaybeUninit::uninit().assume_init() });
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    61
        let mut blocks = [None; 64];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    62
        let mut offset = 0;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    63
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    64
        for i in 0..64 {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    65
            if mask & (164 << i) != 0 {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    66
                blocks[i] = Some(NonNull::new(data[offset..].as_mut_ptr()).unwrap());
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    67
                offset += element_sizes[i] as usize * max_elements as usize;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    68
            }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    69
        }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    70
        Self {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    71
            elements_count: 0,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    72
            max_elements,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    73
            data,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    74
            blocks,
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    75
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    76
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    77
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    78
    fn is_full(&self) -> bool {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    79
        self.elements_count == self.max_elements
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    80
    }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    81
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    82
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    83
#[derive(Clone, Copy, Debug, Default)]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    84
pub struct LookupEntry {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    85
    index: Option<NonZeroU16>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    86
    block_index: u16,
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    87
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    88
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    89
pub struct GearDataManager {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    90
    types: Vec<TypeId>,
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    91
    blocks: Vec<DataBlock>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    92
    block_masks: Vec<u64>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    93
    element_sizes: Box<[u16; 64]>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    94
    lookup: Box<[LookupEntry]>,
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    95
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    96
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    97
impl GearDataManager {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    98
    pub fn new() -> Self {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    99
        Self {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   100
            types: vec![],
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   101
            blocks: vec![],
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   102
            block_masks: vec![],
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   103
            element_sizes: Box::new([0; 64]),
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   104
            lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(),
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   105
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   106
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   107
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   108
    #[inline]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   109
    fn get_type_index<T: 'static>(&self) -> Option<usize> {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   110
        let type_id = TypeId::of::<T>();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   111
        self.types.iter().position(|id| *id == type_id)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   112
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   113
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   114
    fn move_between_blocks(&mut self, from_block_index: u16, from_index: u16, to_block_index: u16) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   115
        let source_mask = self.block_masks[from_block_index as usize];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   116
        let destination_mask = self.block_masks[to_block_index as usize];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   117
        debug_assert!(source_mask & destination_mask == source_mask);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   118
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   119
        let source = &self.blocks[from_block_index as usize];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   120
        let destination = &self.blocks[to_block_index as usize];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   121
        for i in 0..64 {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   122
            unimplemented!()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   123
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   124
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   125
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   126
    fn add_to_block<T: Clone>(&mut self, block_index: u16, value: &T) {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   127
        debug_assert!(self.block_masks[block_index as usize].count_ones() == 1);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   128
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   129
        let block = &mut self.blocks[block_index as usize];
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   130
        debug_assert!(block.elements_count < block.max_elements);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   131
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   132
        unsafe {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   133
            let slice = slice::from_raw_parts_mut(
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   134
                block.data.as_mut_ptr() as *mut T,
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   135
                block.max_elements as usize,
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   136
            );
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   137
            *slice.get_unchecked_mut(block.elements_count as usize) = value.clone();
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   138
        };
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   139
        block.elements_count += 1;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   140
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   141
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   142
    fn remove_from_block(&mut self, block_index: u16, index: u16) {
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   143
        let block = &mut self.blocks[block_index as usize];
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   144
        debug_assert!(index < block.elements_count);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   145
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   146
        for (i, size) in self.element_sizes.iter().cloned().enumerate() {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   147
            if index < block.elements_count - 1 {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   148
                if let Some(mut ptr) = block.blocks[i] {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   149
                    unsafe {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   150
                        std::ptr::copy_nonoverlapping(
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   151
                            ptr.as_ptr()
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   152
                                .add((size * (block.elements_count - 1)) as usize),
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   153
                            ptr.as_ptr().add((size * index) as usize),
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   154
                            size as usize,
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   155
                        );
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   156
                    }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   157
                }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   158
            }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   159
        }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   160
        block.elements_count -= 1;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   161
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   162
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   163
    #[inline]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   164
    fn ensure_group(&mut self, mask: u64) -> u16 {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   165
        if let Some(index) = self
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   166
            .block_masks
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   167
            .iter()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   168
            .enumerate()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   169
            .position(|(i, m)| *m == mask && !self.blocks[i].is_full())
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   170
        {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   171
            index as u16
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   172
        } else {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   173
            self.blocks.push(DataBlock::new(mask, &self.element_sizes));
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   174
            (self.blocks.len() - 1) as u16
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   175
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   176
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   177
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   178
    pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   179
        if let Some(type_index) = self.get_type_index::<T>() {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   180
            let type_bit = 1u64 << type_index as u64;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   181
            let entry = self.lookup[gear_id.get() as usize - 1];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   182
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   183
            if let Some(index) = entry.index {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   184
                let mask = self.block_masks[entry.block_index as usize];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   185
                let new_mask = mask | type_bit;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   186
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   187
                if new_mask != mask {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   188
                    let dest_block_index = self.ensure_group(new_mask);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   189
                    self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   190
                }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   191
            } else {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   192
                let dest_block_index = self.ensure_group(type_bit);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   193
                self.add_to_block(dest_block_index, value);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   194
            }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   195
        } else {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   196
            panic!("Unregistered type")
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   197
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   198
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   199
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   200
    pub fn remove<T: 'static>(&mut self, gear_id: GearId) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   201
        if let Some(type_index) = self.get_type_index::<T>() {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   202
            let entry = self.lookup[gear_id.get() as usize - 1];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   203
            if let Some(index) = entry.index {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   204
                self.remove_from_block(entry.block_index, index.get() - 1);
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   205
            }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   206
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   207
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   208
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   209
    pub fn register<T: 'static>(&mut self) {
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   210
        debug_assert!(!std::mem::needs_drop::<T>());
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   211
        debug_assert!(self.types.len() <= 64);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   212
        debug_assert!(size_of::<T>() <= u16::max_value() as usize);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   213
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   214
        let id = TypeId::of::<T>();
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   215
        if !self.types.contains(&id) {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   216
            self.element_sizes[self.types.len()] = size_of::<T>() as u16;
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   217
            self.types.push(id);
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   218
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   219
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   220
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   221
    fn create_selector(&self, types: &[TypeId]) -> u64 {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   222
        let mut selector = 0u64;
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   223
        for (i, typ) in self.types.iter().enumerate() {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   224
            if types.contains(&typ) {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   225
                selector |= 1u64 << (i as u64)
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   226
            }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   227
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   228
        selector
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   229
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   230
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   231
    pub fn iter<T: TypeTuple + 'static, F: Fn(T) + Copy>(&self, f: F) {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   232
        let mut types = vec![];
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   233
        T::get_types(&mut types);
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   234
        debug_assert!(types.iter().all(|t| self.types.contains(t)));
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   235
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   236
        let types_count = types.len();
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   237
        let selector = self.create_selector(&types);
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   238
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   239
        for (block_index, mask) in self.block_masks.iter().enumerate() {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   240
            if mask & selector == selector {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   241
                let block = &self.blocks[block_index];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   242
                for element_index in 0..block.max_elements {
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   243
                    unsafe {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   244
                        T::iter(unimplemented!(), block.elements_count as usize, f);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   245
                    }
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   246
                }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   247
            }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   248
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   249
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   250
}
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   251
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   252
#[cfg(test)]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   253
mod test {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   254
    use super::GearDataManager;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   255
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   256
    struct Datum {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   257
        value: u32,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   258
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   259
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   260
    #[test]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   261
    fn iteration() {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   262
        let mut manager = GearDataManager::new();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   263
        manager.register::<Datum>();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   264
        manager.iter(|d: (&Datum,)| {});
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   265
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   266
}