author | Wuzzy <Wuzzy@disroot.org> |
Wed, 28 Jun 2023 18:57:00 +0200 | |
changeset 15967 | f362e82cddcf |
parent 15945 | 343b8819b051 |
permissions | -rw-r--r-- |
15354 | 1 |
use super::common::GearId; |
2 |
use std::{ |
|
3 |
any::TypeId, |
|
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
4 |
fmt::{Debug, Error, Formatter}, |
15392 | 5 |
marker::PhantomData, |
15426 | 6 |
mem::{align_of, size_of, MaybeUninit}, |
15354 | 7 |
num::NonZeroU16, |
15368 | 8 |
ptr::{copy_nonoverlapping, null_mut, NonNull}, |
15354 | 9 |
slice, |
10 |
}; |
|
15305 | 11 |
|
15945 | 12 |
const MAX_TYPES: usize = 8; |
13 |
||
15368 | 14 |
pub trait TypeTuple: Sized { |
15945 | 15 |
fn get_types(_types: &mut [TypeId; MAX_TYPES]) -> usize; |
15392 | 16 |
} |
17 |
||
18 |
impl TypeTuple for () { |
|
15945 | 19 |
fn get_types(_types: &mut [TypeId; MAX_TYPES]) -> usize { |
20 |
0 |
|
21 |
} |
|
15392 | 22 |
} |
23 |
||
24 |
impl<T: 'static> TypeTuple for &T { |
|
15945 | 25 |
fn get_types(types: &mut [TypeId; MAX_TYPES]) -> usize { |
26 |
if MAX_TYPES > 0 { |
|
27 |
unsafe { |
|
28 |
*types.get_unchecked_mut(0) = TypeId::of::<T>(); |
|
29 |
} |
|
30 |
1 |
|
31 |
} else { |
|
32 |
0 |
|
33 |
} |
|
15392 | 34 |
} |
35 |
} |
|
36 |
||
37 |
pub trait TypeIter: TypeTuple { |
|
15387 | 38 |
unsafe fn iter<F: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, f: F); |
15305 | 39 |
} |
40 |
||
15369 | 41 |
macro_rules! type_tuple_impl { |
42 |
($($n: literal: $t: ident),+) => { |
|
43 |
impl<$($t: 'static),+> TypeTuple for ($(&$t),+,) { |
|
15945 | 44 |
fn get_types(types: &mut [TypeId; MAX_TYPES]) -> usize { |
45 |
let mut count = 0; |
|
46 |
$({ |
|
47 |
if MAX_TYPES > $n { |
|
48 |
unsafe { |
|
49 |
*types.get_unchecked_mut($n) = TypeId::of::<$t>(); |
|
50 |
} |
|
51 |
count = $n + 1; |
|
52 |
} |
|
53 |
});+ |
|
54 |
count |
|
15368 | 55 |
} |
15392 | 56 |
} |
15305 | 57 |
|
15392 | 58 |
impl<$($t: 'static),+> TypeIter for ($(&$t),+,) { |
15945 | 59 |
unsafe fn iter<FI: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: FI) { |
15368 | 60 |
for i in 0..count { |
15380 | 61 |
f(*(*slices.get_unchecked(0) as *const GearId).add(i), |
62 |
($(&*(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,)); |
|
15368 | 63 |
} |
64 |
} |
|
65 |
} |
|
15354 | 66 |
|
15369 | 67 |
impl<$($t: 'static),+> TypeTuple for ($(&mut $t),+,) { |
15945 | 68 |
fn get_types(types: &mut [TypeId; MAX_TYPES]) -> usize { |
69 |
let mut count = 0; |
|
70 |
$({ |
|
71 |
if MAX_TYPES > $n { |
|
72 |
unsafe { |
|
73 |
*types.get_unchecked_mut($n) = TypeId::of::<$t>(); |
|
74 |
} |
|
75 |
count = $n + 1; |
|
76 |
} |
|
77 |
});+ |
|
78 |
count |
|
15368 | 79 |
} |
15392 | 80 |
} |
15368 | 81 |
|
15392 | 82 |
impl<$($t: 'static),+> TypeIter for ($(&mut $t),+,) { |
15945 | 83 |
unsafe fn iter<FI: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: FI) { |
15368 | 84 |
for i in 0..count { |
15380 | 85 |
f(*(*slices.get_unchecked(0) as *const GearId).add(i), |
86 |
($(&mut *(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,)); |
|
15368 | 87 |
} |
88 |
} |
|
15354 | 89 |
} |
90 |
} |
|
15305 | 91 |
} |
92 |
||
15369 | 93 |
type_tuple_impl!(0: A); |
94 |
type_tuple_impl!(0: A, 1: B); |
|
95 |
type_tuple_impl!(0: A, 1: B, 2: C); |
|
96 |
type_tuple_impl!(0: A, 1: B, 2: C, 3: D); |
|
97 |
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E); |
|
15945 | 98 |
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F); |
99 |
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G); |
|
100 |
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H); |
|
15368 | 101 |
|
15354 | 102 |
const BLOCK_SIZE: usize = 32768; |
103 |
||
104 |
struct DataBlock { |
|
105 |
max_elements: u16, |
|
106 |
elements_count: u16, |
|
107 |
data: Box<[u8; BLOCK_SIZE]>, |
|
15358 | 108 |
component_blocks: [Option<NonNull<u8>>; 64], |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
109 |
element_sizes: Box<[u16]>, |
15305 | 110 |
} |
111 |
||
15354 | 112 |
impl Unpin for DataBlock {} |
113 |
||
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
114 |
impl Debug for DataBlock { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
115 |
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
116 |
write!( |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
117 |
f, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
118 |
"Block ({}/{}) {{\n", |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
119 |
self.elements_count, self.max_elements |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
120 |
)?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
121 |
write!(f, "\tIDs: [")?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
122 |
let id_slice = unsafe { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
123 |
slice::from_raw_parts( |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
124 |
self.data.as_ptr() as *const GearId, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
125 |
self.elements_count as usize, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
126 |
) |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
127 |
}; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
128 |
for gear_id in id_slice { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
129 |
write!(f, "{}, ", gear_id)?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
130 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
131 |
write!(f, "]\n")?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
132 |
for type_index in 0..self.element_sizes.len() { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
133 |
if let Some(ptr) = self.component_blocks[type_index] { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
134 |
write!(f, "\tC{}: [", type_index)?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
135 |
let slice = unsafe { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
136 |
slice::from_raw_parts( |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
137 |
ptr.as_ptr(), |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
138 |
(self.elements_count * self.element_sizes[type_index]) as usize, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
139 |
) |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
140 |
}; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
141 |
for byte in slice { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
142 |
write!(f, "{}, ", byte)?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
143 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
144 |
write!(f, "]\n")?; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
145 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
146 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
147 |
write!(f, "}}\n") |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
148 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
149 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
150 |
|
15354 | 151 |
impl DataBlock { |
15426 | 152 |
fn new(mask: u64, element_sizes: &[u16], element_alignments: &[u8]) -> Self { |
153 |
let total_padding: usize = element_alignments.iter().map(|x| *x as usize).sum(); |
|
15354 | 154 |
let total_size: u16 = element_sizes |
155 |
.iter() |
|
156 |
.enumerate() |
|
15358 | 157 |
.filter(|(i, _)| mask & (1 << *i as u64) != 0) |
15354 | 158 |
.map(|(_, size)| *size) |
159 |
.sum(); |
|
15426 | 160 |
let max_elements = |
161 |
((BLOCK_SIZE - total_padding) / (total_size as usize + size_of::<GearId>())) as u16; |
|
15354 | 162 |
|
15426 | 163 |
//ensure the block memory is aligned to GearId |
164 |
let tmp_data: Box<[GearId; BLOCK_SIZE / size_of::<GearId>()]> = |
|
165 |
Box::new(unsafe { MaybeUninit::uninit().assume_init() }); |
|
15354 | 166 |
let mut data: Box<[u8; BLOCK_SIZE]> = |
15426 | 167 |
unsafe { Box::from_raw(Box::into_raw(tmp_data) as *mut [u8; BLOCK_SIZE]) }; |
168 |
||
15354 | 169 |
let mut blocks = [None; 64]; |
15426 | 170 |
let mut address = unsafe { |
171 |
data.as_mut_ptr() |
|
172 |
.add(size_of::<GearId>() * max_elements as usize) |
|
173 |
}; |
|
15354 | 174 |
|
15941 | 175 |
let mut mask_bits = mask; |
176 |
while mask_bits != 0 { |
|
177 |
let i = mask_bits.trailing_zeros() as usize; |
|
178 |
||
179 |
unsafe { |
|
180 |
address = address.add(address.align_offset(element_alignments[i] as usize)); |
|
181 |
blocks[i] = Some(NonNull::new_unchecked(address)); |
|
182 |
address = address.add(element_sizes[i] as usize * max_elements as usize) |
|
183 |
}; |
|
184 |
||
185 |
mask_bits &= mask_bits - 1; |
|
15354 | 186 |
} |
15426 | 187 |
|
15305 | 188 |
Self { |
15354 | 189 |
elements_count: 0, |
190 |
max_elements, |
|
191 |
data, |
|
15358 | 192 |
component_blocks: blocks, |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
193 |
element_sizes: Box::from(element_sizes), |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
194 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
195 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
196 |
|
15941 | 197 |
#[inline] |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
198 |
fn gear_ids(&self) -> &[GearId] { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
199 |
unsafe { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
200 |
slice::from_raw_parts( |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
201 |
self.data.as_ptr() as *const GearId, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
202 |
self.max_elements as usize, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
203 |
) |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
204 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
205 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
206 |
|
15941 | 207 |
#[inline] |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
208 |
fn gear_ids_mut(&mut self) -> &mut [GearId] { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
209 |
unsafe { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
210 |
slice::from_raw_parts_mut( |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
211 |
self.data.as_mut_ptr() as *mut GearId, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
212 |
self.max_elements as usize, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
213 |
) |
15305 | 214 |
} |
215 |
} |
|
216 |
||
15941 | 217 |
#[inline] |
15354 | 218 |
fn is_full(&self) -> bool { |
219 |
self.elements_count == self.max_elements |
|
220 |
} |
|
15305 | 221 |
} |
222 |
||
15354 | 223 |
#[derive(Clone, Copy, Debug, Default)] |
15379 | 224 |
struct LookupEntry { |
15354 | 225 |
index: Option<NonZeroU16>, |
226 |
block_index: u16, |
|
15305 | 227 |
} |
228 |
||
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
229 |
impl LookupEntry { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
230 |
fn new(block_index: u16, index: u16) -> Self { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
231 |
Self { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
232 |
index: unsafe { Some(NonZeroU16::new_unchecked(index + 1)) }, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
233 |
block_index, |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
234 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
235 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
236 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
237 |
|
15387 | 238 |
#[derive(Copy, Clone, Eq, PartialEq, Debug)] |
239 |
struct BlockMask { |
|
240 |
type_mask: u64, |
|
241 |
tag_mask: u64, |
|
242 |
} |
|
243 |
||
244 |
impl BlockMask { |
|
245 |
#[inline] |
|
246 |
fn new(type_mask: u64, tag_mask: u64) -> Self { |
|
247 |
Self { |
|
248 |
type_mask, |
|
249 |
tag_mask, |
|
250 |
} |
|
251 |
} |
|
252 |
||
253 |
#[inline] |
|
254 |
fn with_type(&self, type_bit: u64) -> Self { |
|
255 |
Self::new(self.type_mask | type_bit, self.tag_mask) |
|
256 |
} |
|
257 |
||
258 |
#[inline] |
|
15942 | 259 |
fn without_type(&self, type_bit: u64) -> Self { |
260 |
Self::new(self.type_mask & !type_bit, self.tag_mask) |
|
261 |
} |
|
262 |
||
263 |
#[inline] |
|
15387 | 264 |
fn with_tag(&self, tag_bit: u64) -> Self { |
265 |
Self::new(self.type_mask, self.tag_mask | tag_bit) |
|
266 |
} |
|
267 |
} |
|
268 |
||
15305 | 269 |
pub struct GearDataManager { |
270 |
types: Vec<TypeId>, |
|
15387 | 271 |
tags: Vec<TypeId>, |
15354 | 272 |
blocks: Vec<DataBlock>, |
15387 | 273 |
block_masks: Vec<BlockMask>, |
15354 | 274 |
element_sizes: Box<[u16; 64]>, |
15426 | 275 |
element_alignments: Box<[u8; 64]>, |
15354 | 276 |
lookup: Box<[LookupEntry]>, |
15305 | 277 |
} |
278 |
||
279 |
impl GearDataManager { |
|
280 |
pub fn new() -> Self { |
|
281 |
Self { |
|
15387 | 282 |
types: Vec::with_capacity(64), |
283 |
tags: Vec::with_capacity(64), |
|
15354 | 284 |
blocks: vec![], |
285 |
block_masks: vec![], |
|
286 |
element_sizes: Box::new([0; 64]), |
|
15426 | 287 |
element_alignments: Box::new([0; 64]), |
15829 | 288 |
lookup: vec![LookupEntry::default(); u16::MAX as usize].into_boxed_slice(), |
15354 | 289 |
} |
290 |
} |
|
291 |
||
292 |
#[inline] |
|
293 |
fn get_type_index<T: 'static>(&self) -> Option<usize> { |
|
294 |
let type_id = TypeId::of::<T>(); |
|
295 |
self.types.iter().position(|id| *id == type_id) |
|
296 |
} |
|
297 |
||
15387 | 298 |
#[inline] |
299 |
fn get_tag_index<T: 'static>(&self) -> Option<usize> { |
|
300 |
let type_id = TypeId::of::<T>(); |
|
301 |
self.tags.iter().position(|id| *id == type_id) |
|
302 |
} |
|
303 |
||
15395
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
304 |
fn move_between_blocks( |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
305 |
&mut self, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
306 |
src_block_index: u16, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
307 |
src_index: u16, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
308 |
dest_block_index: u16, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
309 |
) -> u16 { |
15373 | 310 |
debug_assert!(src_block_index != dest_block_index); |
311 |
let src_mask = self.block_masks[src_block_index as usize]; |
|
312 |
let dest_mask = self.block_masks[dest_block_index as usize]; |
|
15942 | 313 |
debug_assert!(src_mask.type_mask & dest_mask.type_mask != 0); |
15354 | 314 |
|
15373 | 315 |
let src_block = &self.blocks[src_block_index as usize]; |
316 |
let dest_block = &self.blocks[dest_block_index as usize]; |
|
317 |
debug_assert!(src_index < src_block.elements_count); |
|
318 |
debug_assert!(!dest_block.is_full()); |
|
15357 | 319 |
|
15373 | 320 |
let dest_index = dest_block.elements_count; |
15941 | 321 |
|
322 |
let mut type_mask = src_mask.type_mask; |
|
323 |
while type_mask != 0 { |
|
324 |
let i = type_mask.trailing_zeros() as usize; |
|
325 |
||
326 |
let size = self.element_sizes[i]; |
|
327 |
let src_ptr = src_block.component_blocks[i].unwrap().as_ptr(); |
|
15942 | 328 |
if let Some(dest_ptr) = dest_block.component_blocks[i] { |
329 |
let dest_ptr = dest_ptr.as_ptr(); |
|
330 |
unsafe { |
|
331 |
copy_nonoverlapping( |
|
332 |
src_ptr.add((src_index * size) as usize), |
|
333 |
dest_ptr.add((dest_index * size) as usize), |
|
334 |
size as usize, |
|
335 |
); |
|
336 |
} |
|
337 |
} |
|
15941 | 338 |
unsafe { |
339 |
if src_index < src_block.elements_count - 1 { |
|
15357 | 340 |
copy_nonoverlapping( |
15941 | 341 |
src_ptr.add((size * (src_block.elements_count - 1)) as usize), |
342 |
src_ptr.add((size * src_index) as usize), |
|
15373 | 343 |
size as usize, |
15357 | 344 |
); |
345 |
} |
|
346 |
} |
|
15941 | 347 |
|
348 |
type_mask &= type_mask - 1; |
|
15354 | 349 |
} |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
350 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
351 |
let src_block = &mut self.blocks[src_block_index as usize]; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
352 |
let gear_id = src_block.gear_ids()[src_index as usize]; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
353 |
|
15942 | 354 |
if src_index + 1 < src_block.elements_count { |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
355 |
let relocated_index = src_block.elements_count as usize - 1; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
356 |
let gear_ids = src_block.gear_ids_mut(); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
357 |
let relocated_id = gear_ids[relocated_index]; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
358 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
359 |
gear_ids[src_index as usize] = relocated_id; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
360 |
self.lookup[relocated_id.get() as usize - 1] = |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
361 |
LookupEntry::new(src_block_index, src_index); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
362 |
} |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
363 |
src_block.elements_count -= 1; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
364 |
|
15373 | 365 |
let dest_block = &mut self.blocks[dest_block_index as usize]; |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
366 |
let dest_index = dest_block.elements_count; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
367 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
368 |
dest_block.gear_ids_mut()[dest_index as usize] = gear_id; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
369 |
self.lookup[gear_id.get() as usize - 1] = LookupEntry::new(dest_block_index, dest_index); |
15373 | 370 |
dest_block.elements_count += 1; |
15395
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
371 |
dest_block.elements_count - 1 |
15354 | 372 |
} |
373 |
||
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
374 |
fn add_to_block<T: Clone>(&mut self, gear_id: GearId, block_index: u16, value: &T) { |
15387 | 375 |
debug_assert!( |
376 |
self.block_masks[block_index as usize] |
|
377 |
.type_mask |
|
378 |
.count_ones() |
|
379 |
== 1 |
|
380 |
); |
|
15356 | 381 |
|
382 |
let block = &mut self.blocks[block_index as usize]; |
|
383 |
debug_assert!(block.elements_count < block.max_elements); |
|
384 |
||
385 |
unsafe { |
|
15395
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
386 |
*(block.component_blocks[0].unwrap().as_ptr() as *mut T) |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
387 |
.add(block.elements_count as usize) = value.clone(); |
15356 | 388 |
}; |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
389 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
390 |
let index = block.elements_count; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
391 |
self.lookup[gear_id.get() as usize - 1] = LookupEntry::new(block_index, index); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
392 |
block.gear_ids_mut()[index as usize] = gear_id; |
15356 | 393 |
block.elements_count += 1; |
15354 | 394 |
} |
395 |
||
396 |
fn remove_from_block(&mut self, block_index: u16, index: u16) { |
|
15356 | 397 |
let block = &mut self.blocks[block_index as usize]; |
398 |
debug_assert!(index < block.elements_count); |
|
399 |
||
400 |
for (i, size) in self.element_sizes.iter().cloned().enumerate() { |
|
401 |
if index < block.elements_count - 1 { |
|
15358 | 402 |
if let Some(ptr) = block.component_blocks[i] { |
15356 | 403 |
unsafe { |
15357 | 404 |
copy_nonoverlapping( |
15356 | 405 |
ptr.as_ptr() |
406 |
.add((size * (block.elements_count - 1)) as usize), |
|
407 |
ptr.as_ptr().add((size * index) as usize), |
|
408 |
size as usize, |
|
409 |
); |
|
410 |
} |
|
411 |
} |
|
412 |
} |
|
413 |
} |
|
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
414 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
415 |
self.lookup[block.gear_ids()[index as usize].get() as usize - 1] = LookupEntry::default(); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
416 |
if index < block.elements_count - 1 { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
417 |
let relocated_index = block.elements_count as usize - 1; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
418 |
let gear_ids = block.gear_ids_mut(); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
419 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
420 |
gear_ids[index as usize] = gear_ids[relocated_index]; |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
421 |
self.lookup[gear_ids[relocated_index].get() as usize - 1] = |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
422 |
LookupEntry::new(block_index, index); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
423 |
} |
15356 | 424 |
block.elements_count -= 1; |
15354 | 425 |
} |
426 |
||
15395
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
427 |
fn write_component<T: Clone>( |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
428 |
&mut self, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
429 |
block_index: u16, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
430 |
index: u16, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
431 |
type_index: usize, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
432 |
value: &T, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
433 |
) { |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
434 |
debug_assert!(type_index < self.types.len()); |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
435 |
let block = &mut self.blocks[block_index as usize]; |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
436 |
debug_assert!(index < block.elements_count); |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
437 |
|
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
438 |
unsafe { |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
439 |
*(block.component_blocks[type_index].unwrap().as_ptr() as *mut T).add(index as usize) = |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
440 |
value.clone(); |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
441 |
}; |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
442 |
} |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
443 |
|
15354 | 444 |
#[inline] |
15387 | 445 |
fn ensure_block(&mut self, mask: BlockMask) -> u16 { |
15354 | 446 |
if let Some(index) = self |
447 |
.block_masks |
|
448 |
.iter() |
|
449 |
.enumerate() |
|
450 |
.position(|(i, m)| *m == mask && !self.blocks[i].is_full()) |
|
451 |
{ |
|
452 |
index as u16 |
|
453 |
} else { |
|
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
454 |
self.blocks.push(DataBlock::new( |
15387 | 455 |
mask.type_mask, |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
456 |
&self.element_sizes[0..self.types.len()], |
15426 | 457 |
&self.element_alignments[0..self.types.len()], |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
458 |
)); |
15358 | 459 |
self.block_masks.push(mask); |
15354 | 460 |
(self.blocks.len() - 1) as u16 |
461 |
} |
|
462 |
} |
|
463 |
||
464 |
pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) { |
|
465 |
if let Some(type_index) = self.get_type_index::<T>() { |
|
15358 | 466 |
let type_bit = 1 << type_index as u64; |
15354 | 467 |
let entry = self.lookup[gear_id.get() as usize - 1]; |
468 |
||
469 |
if let Some(index) = entry.index { |
|
470 |
let mask = self.block_masks[entry.block_index as usize]; |
|
15387 | 471 |
let new_mask = mask.with_type(type_bit); |
15354 | 472 |
|
473 |
if new_mask != mask { |
|
15358 | 474 |
let dest_block_index = self.ensure_block(new_mask); |
15395
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
475 |
let dest_index = self.move_between_blocks( |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
476 |
entry.block_index, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
477 |
index.get() - 1, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
478 |
dest_block_index, |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
479 |
); |
a87b5e16b863
save data for blocks with more than a single component
alfadur
parents:
15393
diff
changeset
|
480 |
self.write_component(dest_block_index, dest_index, type_index, value); |
15354 | 481 |
} |
482 |
} else { |
|
15387 | 483 |
let dest_block_index = self.ensure_block(BlockMask::new(type_bit, 0)); |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
484 |
self.add_to_block(gear_id, dest_block_index, value); |
15354 | 485 |
} |
486 |
} else { |
|
487 |
panic!("Unregistered type") |
|
488 |
} |
|
489 |
} |
|
490 |
||
15387 | 491 |
pub fn add_tag<T: 'static>(&mut self, gear_id: GearId) { |
492 |
if let Some(tag_index) = self.get_tag_index::<T>() { |
|
493 |
let tag_bit = 1 << tag_index as u64; |
|
494 |
let entry = self.lookup[gear_id.get() as usize - 1]; |
|
495 |
||
496 |
if let Some(index) = entry.index { |
|
497 |
let mask = self.block_masks[entry.block_index as usize]; |
|
498 |
let new_mask = mask.with_tag(tag_bit); |
|
499 |
||
500 |
if new_mask != mask { |
|
501 |
let dest_block_index = self.ensure_block(new_mask); |
|
502 |
self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index); |
|
503 |
} |
|
504 |
} else { |
|
505 |
panic!("Cannot tag a gear with no data") |
|
506 |
} |
|
507 |
} else { |
|
508 |
panic!("Unregistered tag") |
|
509 |
} |
|
510 |
} |
|
511 |
||
15354 | 512 |
pub fn remove<T: 'static>(&mut self, gear_id: GearId) { |
513 |
if let Some(type_index) = self.get_type_index::<T>() { |
|
15942 | 514 |
let type_bit = 1 << type_index as u64; |
15354 | 515 |
let entry = self.lookup[gear_id.get() as usize - 1]; |
15942 | 516 |
|
15354 | 517 |
if let Some(index) = entry.index { |
15942 | 518 |
let mask = self.block_masks[entry.block_index as usize]; |
519 |
let new_mask = mask.without_type(type_bit); |
|
15357 | 520 |
|
15942 | 521 |
if new_mask != mask { |
522 |
if new_mask.type_mask == 0 { |
|
523 |
self.remove_from_block(entry.block_index, index.get() - 1); |
|
524 |
} else { |
|
525 |
let dest_block_index = self.ensure_block(new_mask); |
|
526 |
self.move_between_blocks( |
|
527 |
entry.block_index, |
|
528 |
index.get() - 1, |
|
529 |
dest_block_index, |
|
530 |
); |
|
531 |
} |
|
15357 | 532 |
} |
15354 | 533 |
} |
15357 | 534 |
} else { |
535 |
panic!("Unregistered type") |
|
536 |
} |
|
537 |
} |
|
538 |
||
539 |
pub fn remove_all(&mut self, gear_id: GearId) { |
|
540 |
let entry = self.lookup[gear_id.get() as usize - 1]; |
|
541 |
if let Some(index) = entry.index { |
|
542 |
self.remove_from_block(entry.block_index, index.get() - 1); |
|
15305 | 543 |
} |
544 |
} |
|
545 |
||
546 |
pub fn register<T: 'static>(&mut self) { |
|
15356 | 547 |
debug_assert!(!std::mem::needs_drop::<T>()); |
15829 | 548 |
debug_assert!(size_of::<T>() <= u16::MAX as usize); |
15354 | 549 |
|
15305 | 550 |
let id = TypeId::of::<T>(); |
15387 | 551 |
if size_of::<T>() == 0 { |
552 |
if !self.tags.contains(&id) { |
|
553 |
debug_assert!(self.tags.len() <= 64); |
|
554 |
self.tags.push(id) |
|
555 |
} |
|
556 |
} else { |
|
557 |
if !self.types.contains(&id) { |
|
558 |
debug_assert!(self.types.len() <= 64); |
|
559 |
self.element_sizes[self.types.len()] = size_of::<T>() as u16; |
|
15426 | 560 |
self.element_alignments[self.types.len()] = align_of::<T>() as u8; |
15387 | 561 |
self.types.push(id); |
562 |
} |
|
15305 | 563 |
} |
564 |
} |
|
565 |
||
15392 | 566 |
fn run_impl<T: TypeIter + 'static, F: FnMut(GearId, T)>( |
567 |
&mut self, |
|
568 |
type_selector: u64, |
|
569 |
included_tags: u64, |
|
570 |
type_indices: &[i8], |
|
571 |
mut f: F, |
|
572 |
) { |
|
15945 | 573 |
let mut slices = [null_mut(); MAX_TYPES + 1]; |
15358 | 574 |
|
15354 | 575 |
for (block_index, mask) in self.block_masks.iter().enumerate() { |
15392 | 576 |
if mask.type_mask & type_selector == type_selector |
577 |
&& mask.tag_mask & included_tags == included_tags |
|
578 |
{ |
|
15379 | 579 |
let block = &mut self.blocks[block_index]; |
580 |
slices[0] = block.data.as_mut_ptr(); |
|
581 |
||
15367
d6b4586b271f
make sure component slice order corresponds to the type args
alfadur
parents:
15358
diff
changeset
|
582 |
for (arg_index, type_index) in type_indices.iter().cloned().enumerate() { |
15379 | 583 |
slices[arg_index as usize + 1] = block.component_blocks[type_index as usize] |
15368 | 584 |
.unwrap() |
585 |
.as_ptr() |
|
15354 | 586 |
} |
15358 | 587 |
|
588 |
unsafe { |
|
15945 | 589 |
T::iter( |
590 |
&slices[0..=type_indices.len()], |
|
591 |
block.elements_count as usize, |
|
592 |
|id, x| f(id, x), |
|
593 |
); |
|
15358 | 594 |
} |
15305 | 595 |
} |
596 |
} |
|
597 |
} |
|
15392 | 598 |
|
15829 | 599 |
pub fn get<T: 'static>(&self, gear_id: GearId) -> Option<&T> { |
600 |
let entry = self.lookup[gear_id.get() as usize - 1]; |
|
601 |
match (entry.index, self.get_type_index::<T>()) { |
|
602 |
(Some(index), Some(type_index)) => { |
|
603 |
let block = &self.blocks[entry.block_index as usize]; |
|
604 |
block.component_blocks[type_index].map(|ptr| unsafe { |
|
605 |
&*(ptr.as_ptr() as *const T).add(index.get() as usize - 1) |
|
606 |
}) |
|
607 |
} |
|
608 |
_ => None, |
|
609 |
} |
|
610 |
} |
|
611 |
||
15392 | 612 |
pub fn iter<T: TypeIter + 'static>(&mut self) -> DataIterator<T> { |
15945 | 613 |
let mut arg_types: [TypeId; MAX_TYPES] = unsafe { MaybeUninit::uninit().assume_init() }; |
614 |
let types_count = T::get_types(&mut arg_types); |
|
615 |
let mut type_indices = [-1; MAX_TYPES]; |
|
15392 | 616 |
let mut selector = 0u64; |
617 |
||
15945 | 618 |
for (arg_index, type_id) in arg_types[0..types_count].iter().enumerate() { |
15392 | 619 |
match self.types.iter().position(|t| t == type_id) { |
620 |
Some(i) if selector & (1 << i as u64) != 0 => panic!("Duplicate type"), |
|
621 |
Some(i) => { |
|
622 |
type_indices[arg_index] = i as i8; |
|
623 |
selector |= 1 << i as u64; |
|
624 |
} |
|
625 |
None => panic!("Unregistered type"), |
|
626 |
} |
|
627 |
} |
|
628 |
DataIterator::new(self, selector, type_indices) |
|
629 |
} |
|
630 |
} |
|
631 |
||
632 |
pub struct DataIterator<'a, T> { |
|
633 |
data: &'a mut GearDataManager, |
|
634 |
types: u64, |
|
15945 | 635 |
type_indices: [i8; MAX_TYPES], |
15392 | 636 |
tags: u64, |
637 |
phantom_types: PhantomData<T>, |
|
638 |
} |
|
639 |
||
640 |
impl<'a, T: TypeIter + 'static> DataIterator<'a, T> { |
|
641 |
fn new( |
|
642 |
data: &'a mut GearDataManager, |
|
643 |
types: u64, |
|
15945 | 644 |
type_indices: [i8; MAX_TYPES], |
15392 | 645 |
) -> DataIterator<'a, T> { |
646 |
Self { |
|
647 |
data, |
|
648 |
types, |
|
649 |
type_indices, |
|
650 |
tags: 0, |
|
651 |
phantom_types: PhantomData, |
|
652 |
} |
|
653 |
} |
|
654 |
||
655 |
pub fn with_tags<U: TypeTuple + 'static>(self) -> Self { |
|
15945 | 656 |
let mut tag_types: [TypeId; MAX_TYPES] = unsafe { MaybeUninit::uninit().assume_init() }; |
657 |
let tags_count = U::get_types(&mut tag_types); |
|
15392 | 658 |
let mut tags = 0; |
659 |
||
660 |
for (i, tag) in self.data.tags.iter().enumerate() { |
|
15945 | 661 |
if tag_types[0..tags_count].contains(tag) { |
15392 | 662 |
tags |= 1 << i as u64; |
663 |
} |
|
664 |
} |
|
665 |
Self { tags, ..self } |
|
666 |
} |
|
667 |
||
668 |
#[inline] |
|
669 |
pub fn run<F: FnMut(T)>(&mut self, mut f: F) { |
|
670 |
self.run_id(|_, x| f(x)) |
|
671 |
} |
|
672 |
||
673 |
#[inline] |
|
674 |
pub fn run_id<F: FnMut(GearId, T)>(&mut self, f: F) { |
|
15945 | 675 |
let types_count = self |
676 |
.type_indices |
|
677 |
.iter() |
|
678 |
.position(|i| *i == -1) |
|
679 |
.unwrap_or(self.type_indices.len()); |
|
15392 | 680 |
self.data |
15945 | 681 |
.run_impl(self.types, self.tags, &self.type_indices[0..types_count], f); |
15392 | 682 |
} |
15305 | 683 |
} |
15354 | 684 |
|
685 |
#[cfg(test)] |
|
686 |
mod test { |
|
15358 | 687 |
use super::{super::common::GearId, GearDataManager}; |
15354 | 688 |
|
15358 | 689 |
#[derive(Clone)] |
15942 | 690 |
struct DatumA { |
691 |
value: u32, |
|
692 |
} |
|
693 |
||
694 |
#[derive(Clone)] |
|
695 |
struct DatumB { |
|
15354 | 696 |
value: u32, |
697 |
} |
|
698 |
||
15371 | 699 |
#[derive(Clone)] |
15392 | 700 |
struct Tag; |
15371 | 701 |
|
15354 | 702 |
#[test] |
15829 | 703 |
fn direct_access() { |
704 |
let mut manager = GearDataManager::new(); |
|
15942 | 705 |
manager.register::<DatumA>(); |
15829 | 706 |
for i in 1..=5 { |
15942 | 707 |
manager.add(GearId::new(i as u16).unwrap(), &DatumA { value: i * i }); |
15829 | 708 |
} |
709 |
||
710 |
for i in 1..=5 { |
|
711 |
assert_eq!( |
|
712 |
manager |
|
15942 | 713 |
.get::<DatumA>(GearId::new(i as u16).unwrap()) |
15829 | 714 |
.unwrap() |
715 |
.value, |
|
716 |
i * i |
|
717 |
); |
|
718 |
} |
|
719 |
} |
|
720 |
||
721 |
#[test] |
|
15358 | 722 |
fn single_component_iteration() { |
15354 | 723 |
let mut manager = GearDataManager::new(); |
15942 | 724 |
manager.register::<DatumA>(); |
725 |
||
15358 | 726 |
for i in 1..=5 { |
15942 | 727 |
manager.add(GearId::new(i as u16).unwrap(), &DatumA { value: i }); |
15358 | 728 |
} |
729 |
||
730 |
let mut sum = 0; |
|
15942 | 731 |
manager.iter().run(|(d,): (&DatumA,)| sum += d.value); |
15368 | 732 |
assert_eq!(sum, 15); |
15358 | 733 |
|
15942 | 734 |
manager.iter().run(|(d,): (&mut DatumA,)| d.value += 1); |
735 |
manager.iter().run(|(d,): (&DatumA,)| sum += d.value); |
|
15368 | 736 |
assert_eq!(sum, 35); |
15354 | 737 |
} |
15371 | 738 |
|
739 |
#[test] |
|
15392 | 740 |
fn tagged_component_iteration() { |
15371 | 741 |
let mut manager = GearDataManager::new(); |
15942 | 742 |
manager.register::<DatumA>(); |
15371 | 743 |
manager.register::<Tag>(); |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
744 |
|
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
745 |
for i in 1..=10 { |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
746 |
let gear_id = GearId::new(i as u16).unwrap(); |
15942 | 747 |
manager.add(gear_id, &DatumA { value: i }); |
748 |
} |
|
749 |
||
750 |
for i in (2..=10).step_by(2) { |
|
751 |
let gear_id = GearId::new(i as u16).unwrap(); |
|
752 |
manager.add_tag::<Tag>(gear_id); |
|
15371 | 753 |
} |
754 |
||
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
755 |
let mut sum = 0; |
15942 | 756 |
manager.iter().run(|(d,): (&DatumA,)| sum += d.value); |
15375
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
757 |
assert_eq!(sum, 55); |
37b632d38f14
properly update gear id lookup on block modifications
alfadur
parents:
15373
diff
changeset
|
758 |
|
15392 | 759 |
let mut tag_sum = 0; |
760 |
manager |
|
761 |
.iter() |
|
762 |
.with_tags::<&Tag>() |
|
15942 | 763 |
.run(|(d,): (&DatumA,)| tag_sum += d.value); |
15392 | 764 |
assert_eq!(tag_sum, 30); |
15371 | 765 |
} |
15942 | 766 |
|
767 |
#[test] |
|
768 |
fn removal() { |
|
769 |
let mut manager = GearDataManager::new(); |
|
770 |
manager.register::<DatumA>(); |
|
771 |
manager.register::<DatumB>(); |
|
772 |
||
773 |
for i in 1..=10 { |
|
774 |
let gear_id = GearId::new(i as u16).unwrap(); |
|
775 |
manager.add(gear_id, &DatumA { value: i }); |
|
776 |
manager.add(gear_id, &DatumB { value: i }); |
|
777 |
} |
|
778 |
||
779 |
for i in (1..=10).step_by(2) { |
|
780 |
let gear_id = GearId::new(i as u16).unwrap(); |
|
781 |
manager.remove::<DatumA>(gear_id); |
|
782 |
} |
|
783 |
||
784 |
let mut sum_a = 0; |
|
785 |
manager.iter().run(|(d,): (&DatumA,)| sum_a += d.value); |
|
786 |
assert_eq!(sum_a, 30); |
|
787 |
||
788 |
let mut sum_b = 0; |
|
789 |
manager.iter().run(|(d,): (&DatumB,)| sum_b += d.value); |
|
790 |
assert_eq!(sum_b, 55); |
|
791 |
} |
|
15354 | 792 |
} |