1 //! Small lists of entity references. 2 use crate::EntityRef; 3 use crate::packed_option::ReservedValue; 4 use alloc::vec::Vec; 5 use core::marker::PhantomData; 6 use core::mem; 7 8 #[cfg(feature = "enable-serde")] 9 use serde_derive::{Deserialize, Serialize}; 10 11 /// A small list of entity references allocated from a pool. 12 /// 13 /// An `EntityList<T>` type provides similar functionality to `Vec<T>`, but with some important 14 /// differences in the implementation: 15 /// 16 /// 1. Memory is allocated from a `ListPool<T>` instead of the global heap. 17 /// 2. The footprint of an entity list is 4 bytes, compared with the 24 bytes for `Vec<T>`. 18 /// 3. An entity list doesn't implement `Drop`, leaving it to the pool to manage memory. 19 /// 20 /// The list pool is intended to be used as a LIFO allocator. After building up a larger data 21 /// structure with many list references, the whole thing can be discarded quickly by clearing the 22 /// pool. 23 /// 24 /// # Safety 25 /// 26 /// Entity lists are not as safe to use as `Vec<T>`, but they never jeopardize Rust's memory safety 27 /// guarantees. These are the problems to be aware of: 28 /// 29 /// - If you lose track of an entity list, its memory won't be recycled until the pool is cleared. 30 /// This can cause the pool to grow very large with leaked lists. 31 /// - If entity lists are used after their pool is cleared, they may contain garbage data, and 32 /// modifying them may corrupt other lists in the pool. 33 /// - If an entity list is used with two different pool instances, both pools are likely to become 34 /// corrupted. 35 /// 36 /// Entity lists can be cloned, but that operation should only be used as part of cloning the whole 37 /// function they belong to. *Cloning an entity list does not allocate new memory for the clone*. 38 /// It creates an alias of the same memory. 39 /// 40 /// Entity lists cannot be hashed and compared for equality because it's not possible to compare the 41 /// contents of the list without the pool reference. 42 /// 43 /// # Implementation 44 /// 45 /// The `EntityList` itself is designed to have the smallest possible footprint. This is important 46 /// because it is used inside very compact data structures like `InstructionData`. The list 47 /// contains only a 32-bit index into the pool's memory vector, pointing to the first element of 48 /// the list. A zero value represents the empty list, which is returned by `EntityList::default`. 49 /// 50 /// The pool is just a single `Vec<T>` containing all of the allocated lists. Each list is 51 /// represented as three contiguous parts: 52 /// 53 /// 1. The number of elements in the list. 54 /// 2. The list elements. 55 /// 3. Excess capacity elements. 56 /// 57 /// The total size of the three parts is always a power of two, and the excess capacity is always 58 /// as small as possible. This means that shrinking a list may cause the excess capacity to shrink 59 /// if a smaller power-of-two size becomes available. 60 /// 61 /// Both growing and shrinking a list may cause it to be reallocated in the pool vector. 62 /// 63 /// The index stored in an `EntityList` points to part 2, the list elements. The value 0 is 64 /// reserved for the empty list which isn't allocated in the vector. 65 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 66 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 67 #[repr(C)] 68 pub struct EntityList<T: EntityRef + ReservedValue> { 69 index: u32, 70 unused: PhantomData<T>, 71 } 72 73 /// Create an empty list. 74 impl<T: EntityRef + ReservedValue> Default for EntityList<T> { 75 fn default() -> Self { 76 Self { 77 index: 0, 78 unused: PhantomData, 79 } 80 } 81 } 82 83 /// A memory pool for storing lists of `T`. 84 #[derive(Clone, Debug)] 85 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 86 pub struct ListPool<T: EntityRef + ReservedValue> { 87 // The main array containing the lists. 88 data: Vec<T>, 89 90 // Heads of the free lists, one for each size class. 91 free: Vec<usize>, 92 } 93 94 impl<T: EntityRef + ReservedValue> PartialEq for ListPool<T> { 95 fn eq(&self, other: &Self) -> bool { 96 // ignore the free list 97 self.data == other.data 98 } 99 } 100 101 impl<T: core::hash::Hash + EntityRef + ReservedValue> core::hash::Hash for ListPool<T> { 102 fn hash<H: __core::hash::Hasher>(&self, state: &mut H) { 103 // ignore the free list 104 self.data.hash(state); 105 } 106 } 107 108 impl<T: EntityRef + ReservedValue> Default for ListPool<T> { 109 fn default() -> Self { 110 Self::new() 111 } 112 } 113 114 /// Lists are allocated in sizes that are powers of two, starting from 4. 115 /// Each power of two is assigned a size class number, so the size is `4 << SizeClass`. 116 type SizeClass = u8; 117 118 /// Get the size of a given size class. The size includes the length field, so the maximum list 119 /// length is one less than the class size. 120 #[inline] 121 fn sclass_size(sclass: SizeClass) -> usize { 122 4 << sclass 123 } 124 125 /// Get the size class to use for a given list length. 126 /// This always leaves room for the length element in addition to the list elements. 127 #[inline] 128 fn sclass_for_length(len: usize) -> SizeClass { 129 30 - (len as u32 | 3).leading_zeros() as SizeClass 130 } 131 132 /// Is `len` the minimum length in its size class? 133 #[inline] 134 fn is_sclass_min_length(len: usize) -> bool { 135 len > 3 && len.is_power_of_two() 136 } 137 138 impl<T: EntityRef + ReservedValue> ListPool<T> { 139 /// Create a new list pool. 140 pub fn new() -> Self { 141 Self { 142 data: Vec::new(), 143 free: Vec::new(), 144 } 145 } 146 147 /// Create a new list pool with the given capacity for data pre-allocated. 148 pub fn with_capacity(len: usize) -> Self { 149 Self { 150 data: Vec::with_capacity(len), 151 free: Vec::new(), 152 } 153 } 154 155 /// Get the capacity of this pool. This will be somewhat higher 156 /// than the total length of lists that can be stored without 157 /// reallocating, because of internal metadata overheads. It is 158 /// mostly useful to allow another pool to be allocated that is 159 /// likely to hold data transferred from this one without the need 160 /// to grow. 161 pub fn capacity(&self) -> usize { 162 self.data.capacity() 163 } 164 165 /// Clear the pool, forgetting about all lists that use it. 166 /// 167 /// This invalidates any existing entity lists that used this pool to allocate memory. 168 /// 169 /// The pool's memory is not released to the operating system, but kept around for faster 170 /// allocation in the future. 171 pub fn clear(&mut self) { 172 self.data.clear(); 173 self.free.clear(); 174 } 175 176 /// Read the length of a list field, if it exists. 177 fn len_of(&self, list: &EntityList<T>) -> Option<usize> { 178 let idx = list.index as usize; 179 // `idx` points at the list elements. The list length is encoded in the element immediately 180 // before the list elements. 181 // 182 // The `wrapping_sub` handles the special case 0, which is the empty list. This way, the 183 // cost of the bounds check that we have to pay anyway is co-opted to handle the special 184 // case of the empty list. 185 self.data.get(idx.wrapping_sub(1)).map(|len| len.index()) 186 } 187 188 /// Allocate a storage block with a size given by `sclass`. 189 /// 190 /// Returns the first index of an available segment of `self.data` containing 191 /// `sclass_size(sclass)` elements. The allocated memory is filled with reserved 192 /// values. 193 fn alloc(&mut self, sclass: SizeClass) -> usize { 194 // First try the free list for this size class. 195 match self.free.get(sclass as usize).cloned() { 196 Some(head) if head > 0 => { 197 // The free list pointers are offset by 1, using 0 to terminate the list. 198 // A block on the free list has two entries: `[ 0, next ]`. 199 // The 0 is where the length field would be stored for a block in use. 200 // The free list heads and the next pointer point at the `next` field. 201 self.free[sclass as usize] = self.data[head].index(); 202 head - 1 203 } 204 _ => { 205 // Nothing on the free list. Allocate more memory. 206 let offset = self.data.len(); 207 self.data 208 .resize(offset + sclass_size(sclass), T::reserved_value()); 209 offset 210 } 211 } 212 } 213 214 /// Free a storage block with a size given by `sclass`. 215 /// 216 /// This must be a block that was previously allocated by `alloc()` with the same size class. 217 fn free(&mut self, block: usize, sclass: SizeClass) { 218 let sclass = sclass as usize; 219 220 // Make sure we have a free-list head for `sclass`. 221 if self.free.len() <= sclass { 222 self.free.resize(sclass + 1, 0); 223 } 224 225 // Make sure the length field is cleared. 226 self.data[block] = T::new(0); 227 // Insert the block on the free list which is a single linked list. 228 self.data[block + 1] = T::new(self.free[sclass]); 229 self.free[sclass] = block + 1 230 } 231 232 /// Returns two mutable slices representing the two requested blocks. 233 /// 234 /// The two returned slices can be longer than the blocks. Each block is located at the front 235 /// of the respective slice. 236 fn mut_slices(&mut self, block0: usize, block1: usize) -> (&mut [T], &mut [T]) { 237 if block0 < block1 { 238 let (s0, s1) = self.data.split_at_mut(block1); 239 (&mut s0[block0..], s1) 240 } else { 241 let (s1, s0) = self.data.split_at_mut(block0); 242 (s0, &mut s1[block1..]) 243 } 244 } 245 246 /// Reallocate a block to a different size class. 247 /// 248 /// Copy `elems_to_copy` elements from the old to the new block. 249 fn realloc( 250 &mut self, 251 block: usize, 252 from_sclass: SizeClass, 253 to_sclass: SizeClass, 254 elems_to_copy: usize, 255 ) -> usize { 256 debug_assert!(elems_to_copy <= sclass_size(from_sclass)); 257 debug_assert!(elems_to_copy <= sclass_size(to_sclass)); 258 let new_block = self.alloc(to_sclass); 259 260 if elems_to_copy > 0 { 261 let (old, new) = self.mut_slices(block, new_block); 262 (&mut new[0..elems_to_copy]).copy_from_slice(&old[0..elems_to_copy]); 263 } 264 265 self.free(block, from_sclass); 266 new_block 267 } 268 } 269 270 impl<T: EntityRef + ReservedValue> EntityList<T> { 271 /// Create a new empty list. 272 pub fn new() -> Self { 273 Default::default() 274 } 275 276 /// Create a new list with the contents initialized from a slice. 277 pub fn from_slice(slice: &[T], pool: &mut ListPool<T>) -> Self { 278 let len = slice.len(); 279 if len == 0 { 280 return Self::new(); 281 } 282 283 let block = pool.alloc(sclass_for_length(len)); 284 pool.data[block] = T::new(len); 285 pool.data[block + 1..=block + len].copy_from_slice(slice); 286 287 Self { 288 index: (block + 1) as u32, 289 unused: PhantomData, 290 } 291 } 292 293 /// Returns `true` if the list has a length of 0. 294 pub fn is_empty(&self) -> bool { 295 // 0 is a magic value for the empty list. Any list in the pool array must have a positive 296 // length. 297 self.index == 0 298 } 299 300 /// Get the number of elements in the list. 301 pub fn len(&self, pool: &ListPool<T>) -> usize { 302 // Both the empty list and any invalidated old lists will return `None`. 303 pool.len_of(self).unwrap_or(0) 304 } 305 306 /// Returns `true` if the list is valid 307 pub fn is_valid(&self, pool: &ListPool<T>) -> bool { 308 // We consider an empty list to be valid 309 self.is_empty() || pool.len_of(self) != None 310 } 311 312 /// Get the list as a slice. 313 pub fn as_slice<'a>(&self, pool: &'a ListPool<T>) -> &'a [T] { 314 let idx = self.index as usize; 315 match pool.len_of(self) { 316 None => &[], 317 Some(len) => &pool.data[idx..idx + len], 318 } 319 } 320 321 /// Get a single element from the list. 322 pub fn get(&self, index: usize, pool: &ListPool<T>) -> Option<T> { 323 self.as_slice(pool).get(index).cloned() 324 } 325 326 /// Get the first element from the list. 327 pub fn first(&self, pool: &ListPool<T>) -> Option<T> { 328 if self.is_empty() { 329 None 330 } else { 331 Some(pool.data[self.index as usize]) 332 } 333 } 334 335 /// Get the list as a mutable slice. 336 pub fn as_mut_slice<'a>(&'a mut self, pool: &'a mut ListPool<T>) -> &'a mut [T] { 337 let idx = self.index as usize; 338 match pool.len_of(self) { 339 None => &mut [], 340 Some(len) => &mut pool.data[idx..idx + len], 341 } 342 } 343 344 /// Get a mutable reference to a single element from the list. 345 pub fn get_mut<'a>(&'a mut self, index: usize, pool: &'a mut ListPool<T>) -> Option<&'a mut T> { 346 self.as_mut_slice(pool).get_mut(index) 347 } 348 349 /// Create a deep clone of the list, which does not alias the original list. 350 pub fn deep_clone(&self, pool: &mut ListPool<T>) -> Self { 351 match pool.len_of(self) { 352 None => return Self::new(), 353 Some(len) => { 354 let src = self.index as usize; 355 let block = pool.alloc(sclass_for_length(len)); 356 pool.data[block] = T::new(len); 357 pool.data.copy_within(src..src + len, block + 1); 358 359 Self { 360 index: (block + 1) as u32, 361 unused: PhantomData, 362 } 363 } 364 } 365 } 366 367 /// Removes all elements from the list. 368 /// 369 /// The memory used by the list is put back in the pool. 370 pub fn clear(&mut self, pool: &mut ListPool<T>) { 371 let idx = self.index as usize; 372 match pool.len_of(self) { 373 None => debug_assert_eq!(idx, 0, "Invalid pool"), 374 Some(len) => pool.free(idx - 1, sclass_for_length(len)), 375 } 376 // Switch back to the empty list representation which has no storage. 377 self.index = 0; 378 } 379 380 /// Take all elements from this list and return them as a new list. Leave this list empty. 381 /// 382 /// This is the equivalent of `Option::take()`. 383 pub fn take(&mut self) -> Self { 384 mem::replace(self, Default::default()) 385 } 386 387 /// Appends an element to the back of the list. 388 /// Returns the index where the element was inserted. 389 pub fn push(&mut self, element: T, pool: &mut ListPool<T>) -> usize { 390 let idx = self.index as usize; 391 match pool.len_of(self) { 392 None => { 393 // This is an empty list. Allocate a block and set length=1. 394 debug_assert_eq!(idx, 0, "Invalid pool"); 395 let block = pool.alloc(sclass_for_length(1)); 396 pool.data[block] = T::new(1); 397 pool.data[block + 1] = element; 398 self.index = (block + 1) as u32; 399 0 400 } 401 Some(len) => { 402 // Do we need to reallocate? 403 let new_len = len + 1; 404 let block; 405 if is_sclass_min_length(new_len) { 406 // Reallocate, preserving length + all old elements. 407 let sclass = sclass_for_length(len); 408 block = pool.realloc(idx - 1, sclass, sclass + 1, len + 1); 409 self.index = (block + 1) as u32; 410 } else { 411 block = idx - 1; 412 } 413 pool.data[block + new_len] = element; 414 pool.data[block] = T::new(new_len); 415 len 416 } 417 } 418 } 419 420 /// Grow list by adding `count` reserved-value elements at the end. 421 /// 422 /// Returns a mutable slice representing the whole list. 423 fn grow<'a>(&'a mut self, count: usize, pool: &'a mut ListPool<T>) -> &'a mut [T] { 424 let idx = self.index as usize; 425 let new_len; 426 let block; 427 match pool.len_of(self) { 428 None => { 429 // This is an empty list. Allocate a block. 430 debug_assert_eq!(idx, 0, "Invalid pool"); 431 if count == 0 { 432 return &mut []; 433 } 434 new_len = count; 435 block = pool.alloc(sclass_for_length(new_len)); 436 self.index = (block + 1) as u32; 437 } 438 Some(len) => { 439 // Do we need to reallocate? 440 let sclass = sclass_for_length(len); 441 new_len = len + count; 442 let new_sclass = sclass_for_length(new_len); 443 if new_sclass != sclass { 444 block = pool.realloc(idx - 1, sclass, new_sclass, len + 1); 445 self.index = (block + 1) as u32; 446 } else { 447 block = idx - 1; 448 } 449 } 450 } 451 pool.data[block] = T::new(new_len); 452 &mut pool.data[block + 1..block + 1 + new_len] 453 } 454 455 /// Constructs a list from an iterator. 456 pub fn from_iter<I>(elements: I, pool: &mut ListPool<T>) -> Self 457 where 458 I: IntoIterator<Item = T>, 459 { 460 let mut list = Self::new(); 461 list.extend(elements, pool); 462 list 463 } 464 465 /// Appends multiple elements to the back of the list. 466 pub fn extend<I>(&mut self, elements: I, pool: &mut ListPool<T>) 467 where 468 I: IntoIterator<Item = T>, 469 { 470 let iterator = elements.into_iter(); 471 let (len, upper) = iterator.size_hint(); 472 // On most iterators this check is optimized down to `true`. 473 if upper == Some(len) { 474 let data = self.grow(len, pool); 475 let offset = data.len() - len; 476 for (src, dst) in iterator.zip(data[offset..].iter_mut()) { 477 *dst = src; 478 } 479 } else { 480 for x in iterator { 481 self.push(x, pool); 482 } 483 } 484 } 485 486 /// Copies a slice from an entity list in the same pool to a position in this one. 487 /// 488 /// Will panic if `self` is the same list as `other`. 489 pub fn copy_from( 490 &mut self, 491 other: &Self, 492 slice: impl core::ops::RangeBounds<usize>, 493 index: usize, 494 pool: &mut ListPool<T>, 495 ) { 496 assert!( 497 index <= self.len(pool), 498 "attempted to copy a slice out of bounds of `self`" 499 ); 500 assert_ne!( 501 self.index, other.index, 502 "cannot copy within one `EntityList`" 503 ); 504 505 let (other_index, other_len) = (other.index, other.len(pool)); 506 507 let start = match slice.start_bound() { 508 core::ops::Bound::Included(&x) => x, 509 core::ops::Bound::Excluded(&x) => x + 1, 510 core::ops::Bound::Unbounded => 0, 511 } + other_index as usize; 512 let end = match slice.end_bound() { 513 core::ops::Bound::Included(&x) => x + 1, 514 core::ops::Bound::Excluded(&x) => x, 515 core::ops::Bound::Unbounded => other_len, 516 } + other_index as usize; 517 let count = end - start; 518 assert!( 519 count <= other_len, 520 "attempted to copy a slice from out of bounds of `other`" 521 ); 522 523 self.grow_at(index, count, pool); 524 pool.data 525 .copy_within(start..end, index + self.index as usize); 526 } 527 528 /// Inserts an element as position `index` in the list, shifting all elements after it to the 529 /// right. 530 pub fn insert(&mut self, index: usize, element: T, pool: &mut ListPool<T>) { 531 // Increase size by 1. 532 self.push(element, pool); 533 534 // Move tail elements. 535 let seq = self.as_mut_slice(pool); 536 if index < seq.len() { 537 let tail = &mut seq[index..]; 538 for i in (1..tail.len()).rev() { 539 tail[i] = tail[i - 1]; 540 } 541 tail[0] = element; 542 } else { 543 debug_assert_eq!(index, seq.len()); 544 } 545 } 546 547 /// Removes the last element from the list. 548 fn remove_last(&mut self, len: usize, pool: &mut ListPool<T>) { 549 // Check if we deleted the last element. 550 if len == 1 { 551 self.clear(pool); 552 return; 553 } 554 555 // Do we need to reallocate to a smaller size class? 556 let mut block = self.index as usize - 1; 557 if is_sclass_min_length(len) { 558 let sclass = sclass_for_length(len); 559 block = pool.realloc(block, sclass, sclass - 1, len); 560 self.index = (block + 1) as u32; 561 } 562 563 // Finally adjust the length. 564 pool.data[block] = T::new(len - 1); 565 } 566 567 /// Removes the element at position `index` from the list. Potentially linear complexity. 568 pub fn remove(&mut self, index: usize, pool: &mut ListPool<T>) { 569 let len; 570 { 571 let seq = self.as_mut_slice(pool); 572 len = seq.len(); 573 debug_assert!(index < len); 574 575 // Copy elements down. 576 for i in index..len - 1 { 577 seq[i] = seq[i + 1]; 578 } 579 } 580 581 self.remove_last(len, pool); 582 } 583 584 /// Removes the element at `index` in constant time by switching it with the last element of 585 /// the list. 586 pub fn swap_remove(&mut self, index: usize, pool: &mut ListPool<T>) { 587 let seq = self.as_mut_slice(pool); 588 let len = seq.len(); 589 debug_assert!(index < len); 590 if index != len - 1 { 591 seq.swap(index, len - 1); 592 } 593 594 self.remove_last(len, pool); 595 } 596 597 /// Shortens the list down to `len` elements. 598 /// 599 /// Does nothing if the list is already shorter than `len`. 600 pub fn truncate(&mut self, new_len: usize, pool: &mut ListPool<T>) { 601 if new_len == 0 { 602 self.clear(pool); 603 return; 604 } 605 606 match pool.len_of(self) { 607 None => return, 608 Some(len) => { 609 if len <= new_len { 610 return; 611 } 612 613 let block; 614 let idx = self.index as usize; 615 let sclass = sclass_for_length(len); 616 let new_sclass = sclass_for_length(new_len); 617 if sclass != new_sclass { 618 block = pool.realloc(idx - 1, sclass, new_sclass, new_len + 1); 619 self.index = (block + 1) as u32; 620 } else { 621 block = idx - 1; 622 } 623 pool.data[block] = T::new(new_len); 624 } 625 } 626 } 627 628 /// Grow the list by inserting `count` elements at `index`. 629 /// 630 /// The new elements are not initialized, they will contain whatever happened to be in memory. 631 /// Since the memory comes from the pool, this will be either zero entity references or 632 /// whatever where in a previously deallocated list. 633 pub fn grow_at(&mut self, index: usize, count: usize, pool: &mut ListPool<T>) { 634 let data = self.grow(count, pool); 635 636 // Copy elements after `index` up. 637 for i in (index + count..data.len()).rev() { 638 data[i] = data[i - count]; 639 } 640 } 641 } 642 643 #[cfg(test)] 644 mod tests { 645 use super::*; 646 647 /// An opaque reference to an instruction in a function. 648 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] 649 pub struct Inst(u32); 650 entity_impl!(Inst, "inst"); 651 652 #[test] 653 fn size_classes() { 654 assert_eq!(sclass_size(0), 4); 655 assert_eq!(sclass_for_length(0), 0); 656 assert_eq!(sclass_for_length(1), 0); 657 assert_eq!(sclass_for_length(2), 0); 658 assert_eq!(sclass_for_length(3), 0); 659 assert_eq!(sclass_for_length(4), 1); 660 assert_eq!(sclass_for_length(7), 1); 661 assert_eq!(sclass_for_length(8), 2); 662 assert_eq!(sclass_size(1), 8); 663 for l in 0..300 { 664 assert!(sclass_size(sclass_for_length(l)) >= l + 1); 665 } 666 } 667 668 #[test] 669 fn block_allocator() { 670 let mut pool = ListPool::<Inst>::new(); 671 let b1 = pool.alloc(0); 672 let b2 = pool.alloc(1); 673 let b3 = pool.alloc(0); 674 assert_ne!(b1, b2); 675 assert_ne!(b1, b3); 676 assert_ne!(b2, b3); 677 pool.free(b2, 1); 678 let b2a = pool.alloc(1); 679 let b2b = pool.alloc(1); 680 assert_ne!(b2a, b2b); 681 // One of these should reuse the freed block. 682 assert!(b2a == b2 || b2b == b2); 683 684 // Check the free lists for a size class smaller than the largest seen so far. 685 pool.free(b1, 0); 686 pool.free(b3, 0); 687 let b1a = pool.alloc(0); 688 let b3a = pool.alloc(0); 689 assert_ne!(b1a, b3a); 690 assert!(b1a == b1 || b1a == b3); 691 assert!(b3a == b1 || b3a == b3); 692 } 693 694 #[test] 695 fn empty_list() { 696 let pool = &mut ListPool::<Inst>::new(); 697 let mut list = EntityList::<Inst>::default(); 698 { 699 let ilist = &list; 700 assert!(ilist.is_empty()); 701 assert_eq!(ilist.len(pool), 0); 702 assert_eq!(ilist.as_slice(pool), &[]); 703 assert_eq!(ilist.get(0, pool), None); 704 assert_eq!(ilist.get(100, pool), None); 705 } 706 assert_eq!(list.as_mut_slice(pool), &[]); 707 assert_eq!(list.get_mut(0, pool), None); 708 assert_eq!(list.get_mut(100, pool), None); 709 710 list.clear(pool); 711 assert!(list.is_empty()); 712 assert_eq!(list.len(pool), 0); 713 assert_eq!(list.as_slice(pool), &[]); 714 assert_eq!(list.first(pool), None); 715 } 716 717 #[test] 718 fn from_slice() { 719 let pool = &mut ListPool::<Inst>::new(); 720 721 let list = EntityList::<Inst>::from_slice(&[Inst(0), Inst(1)], pool); 722 assert!(!list.is_empty()); 723 assert_eq!(list.len(pool), 2); 724 assert_eq!(list.as_slice(pool), &[Inst(0), Inst(1)]); 725 assert_eq!(list.get(0, pool), Some(Inst(0))); 726 assert_eq!(list.get(100, pool), None); 727 728 let list = EntityList::<Inst>::from_slice(&[], pool); 729 assert!(list.is_empty()); 730 assert_eq!(list.len(pool), 0); 731 assert_eq!(list.as_slice(pool), &[]); 732 assert_eq!(list.get(0, pool), None); 733 assert_eq!(list.get(100, pool), None); 734 } 735 736 #[test] 737 fn push() { 738 let pool = &mut ListPool::<Inst>::new(); 739 let mut list = EntityList::<Inst>::default(); 740 741 let i1 = Inst::new(1); 742 let i2 = Inst::new(2); 743 let i3 = Inst::new(3); 744 let i4 = Inst::new(4); 745 746 assert_eq!(list.push(i1, pool), 0); 747 assert_eq!(list.len(pool), 1); 748 assert!(!list.is_empty()); 749 assert_eq!(list.as_slice(pool), &[i1]); 750 assert_eq!(list.first(pool), Some(i1)); 751 assert_eq!(list.get(0, pool), Some(i1)); 752 assert_eq!(list.get(1, pool), None); 753 754 assert_eq!(list.push(i2, pool), 1); 755 assert_eq!(list.len(pool), 2); 756 assert!(!list.is_empty()); 757 assert_eq!(list.as_slice(pool), &[i1, i2]); 758 assert_eq!(list.first(pool), Some(i1)); 759 assert_eq!(list.get(0, pool), Some(i1)); 760 assert_eq!(list.get(1, pool), Some(i2)); 761 assert_eq!(list.get(2, pool), None); 762 763 assert_eq!(list.push(i3, pool), 2); 764 assert_eq!(list.len(pool), 3); 765 assert!(!list.is_empty()); 766 assert_eq!(list.as_slice(pool), &[i1, i2, i3]); 767 assert_eq!(list.first(pool), Some(i1)); 768 assert_eq!(list.get(0, pool), Some(i1)); 769 assert_eq!(list.get(1, pool), Some(i2)); 770 assert_eq!(list.get(2, pool), Some(i3)); 771 assert_eq!(list.get(3, pool), None); 772 773 // This triggers a reallocation. 774 assert_eq!(list.push(i4, pool), 3); 775 assert_eq!(list.len(pool), 4); 776 assert!(!list.is_empty()); 777 assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4]); 778 assert_eq!(list.first(pool), Some(i1)); 779 assert_eq!(list.get(0, pool), Some(i1)); 780 assert_eq!(list.get(1, pool), Some(i2)); 781 assert_eq!(list.get(2, pool), Some(i3)); 782 assert_eq!(list.get(3, pool), Some(i4)); 783 assert_eq!(list.get(4, pool), None); 784 785 list.extend([i1, i1, i2, i2, i3, i3, i4, i4].iter().cloned(), pool); 786 assert_eq!(list.len(pool), 12); 787 assert_eq!( 788 list.as_slice(pool), 789 &[i1, i2, i3, i4, i1, i1, i2, i2, i3, i3, i4, i4] 790 ); 791 792 let list2 = EntityList::from_iter([i1, i1, i2, i2, i3, i3, i4, i4].iter().cloned(), pool); 793 assert_eq!(list2.len(pool), 8); 794 assert_eq!(list2.as_slice(pool), &[i1, i1, i2, i2, i3, i3, i4, i4]); 795 } 796 797 #[test] 798 fn insert_remove() { 799 let pool = &mut ListPool::<Inst>::new(); 800 let mut list = EntityList::<Inst>::default(); 801 802 let i1 = Inst::new(1); 803 let i2 = Inst::new(2); 804 let i3 = Inst::new(3); 805 let i4 = Inst::new(4); 806 807 list.insert(0, i4, pool); 808 assert_eq!(list.as_slice(pool), &[i4]); 809 810 list.insert(0, i3, pool); 811 assert_eq!(list.as_slice(pool), &[i3, i4]); 812 813 list.insert(2, i2, pool); 814 assert_eq!(list.as_slice(pool), &[i3, i4, i2]); 815 816 list.insert(2, i1, pool); 817 assert_eq!(list.as_slice(pool), &[i3, i4, i1, i2]); 818 819 list.remove(3, pool); 820 assert_eq!(list.as_slice(pool), &[i3, i4, i1]); 821 822 list.remove(2, pool); 823 assert_eq!(list.as_slice(pool), &[i3, i4]); 824 825 list.remove(0, pool); 826 assert_eq!(list.as_slice(pool), &[i4]); 827 828 list.remove(0, pool); 829 assert_eq!(list.as_slice(pool), &[]); 830 assert!(list.is_empty()); 831 } 832 833 #[test] 834 fn growing() { 835 let pool = &mut ListPool::<Inst>::new(); 836 let mut list = EntityList::<Inst>::default(); 837 838 let i1 = Inst::new(1); 839 let i2 = Inst::new(2); 840 let i3 = Inst::new(3); 841 let i4 = Inst::new(4); 842 843 // This is not supposed to change the list. 844 list.grow_at(0, 0, pool); 845 assert_eq!(list.len(pool), 0); 846 assert!(list.is_empty()); 847 848 list.grow_at(0, 2, pool); 849 assert_eq!(list.len(pool), 2); 850 851 list.as_mut_slice(pool).copy_from_slice(&[i2, i3]); 852 853 list.grow_at(1, 0, pool); 854 assert_eq!(list.as_slice(pool), &[i2, i3]); 855 856 list.grow_at(1, 1, pool); 857 list.as_mut_slice(pool)[1] = i1; 858 assert_eq!(list.as_slice(pool), &[i2, i1, i3]); 859 860 // Append nothing at the end. 861 list.grow_at(3, 0, pool); 862 assert_eq!(list.as_slice(pool), &[i2, i1, i3]); 863 864 // Append something at the end. 865 list.grow_at(3, 1, pool); 866 list.as_mut_slice(pool)[3] = i4; 867 assert_eq!(list.as_slice(pool), &[i2, i1, i3, i4]); 868 } 869 870 #[test] 871 fn deep_clone() { 872 let pool = &mut ListPool::<Inst>::new(); 873 874 let i1 = Inst::new(1); 875 let i2 = Inst::new(2); 876 let i3 = Inst::new(3); 877 let i4 = Inst::new(4); 878 879 let mut list1 = EntityList::from_slice(&[i1, i2, i3], pool); 880 let list2 = list1.deep_clone(pool); 881 assert_eq!(list1.as_slice(pool), &[i1, i2, i3]); 882 assert_eq!(list2.as_slice(pool), &[i1, i2, i3]); 883 884 list1.as_mut_slice(pool)[0] = i4; 885 assert_eq!(list1.as_slice(pool), &[i4, i2, i3]); 886 assert_eq!(list2.as_slice(pool), &[i1, i2, i3]); 887 } 888 889 #[test] 890 fn truncate() { 891 let pool = &mut ListPool::<Inst>::new(); 892 893 let i1 = Inst::new(1); 894 let i2 = Inst::new(2); 895 let i3 = Inst::new(3); 896 let i4 = Inst::new(4); 897 898 let mut list = EntityList::from_slice(&[i1, i2, i3, i4, i1, i2, i3, i4], pool); 899 assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4, i1, i2, i3, i4]); 900 list.truncate(6, pool); 901 assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4, i1, i2]); 902 list.truncate(9, pool); 903 assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4, i1, i2]); 904 list.truncate(2, pool); 905 assert_eq!(list.as_slice(pool), &[i1, i2]); 906 list.truncate(0, pool); 907 assert!(list.is_empty()); 908 } 909 910 #[test] 911 fn copy_from() { 912 let pool = &mut ListPool::<Inst>::new(); 913 914 let i1 = Inst::new(1); 915 let i2 = Inst::new(2); 916 let i3 = Inst::new(3); 917 let i4 = Inst::new(4); 918 919 let mut list = EntityList::from_slice(&[i1, i2, i3, i4], pool); 920 assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4]); 921 let list2 = EntityList::from_slice(&[i4, i3, i2, i1], pool); 922 assert_eq!(list2.as_slice(pool), &[i4, i3, i2, i1]); 923 list.copy_from(&list2, 0..0, 0, pool); 924 assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4]); 925 list.copy_from(&list2, 0..4, 0, pool); 926 assert_eq!(list.as_slice(pool), &[i4, i3, i2, i1, i1, i2, i3, i4]); 927 } 928 929 #[test] 930 #[should_panic] 931 fn copy_from_self() { 932 let pool = &mut ListPool::<Inst>::new(); 933 934 let i1 = Inst::new(1); 935 let i2 = Inst::new(2); 936 let i3 = Inst::new(3); 937 let i4 = Inst::new(4); 938 939 let mut list = EntityList::from_slice(&[i4, i3, i2, i1, i1, i2, i3, i4], pool); 940 let list_again = list; 941 assert_eq!(list.as_slice(pool), &[i4, i3, i2, i1, i1, i2, i3, i4]); 942 // Panic should occur on the line below because `list.index == other.index` 943 list.copy_from(&list_again, 0..=1, 8, pool); 944 assert_eq!( 945 list.as_slice(pool), 946 &[i4, i3, i2, i1, i1, i2, i3, i4, i4, i3] 947 ); 948 list.copy_from(&list_again, .., 7, pool); 949 assert_eq!( 950 list.as_slice(pool), 951 &[ 952 i4, i3, i2, i1, i1, i2, i4, i3, i2, i1, i1, i2, i3, i4, i4, i3, i3, i4, i4, i3 953 ] 954 ) 955 } 956 } 957