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> {
default() -> Self75     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> {
eq(&self, other: &Self) -> bool95     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> {
hash<H: __core::hash::Hasher>(&self, state: &mut H)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> {
default() -> Self109     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]
sclass_size(sclass: SizeClass) -> usize121 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]
sclass_for_length(len: usize) -> SizeClass128 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]
is_sclass_min_length(len: usize) -> bool134 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.
new() -> Self140     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.
with_capacity(len: usize) -> Self148     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.
capacity(&self) -> usize161     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.
clear(&mut self)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.
len_of(&self, list: &EntityList<T>) -> Option<usize>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.
alloc(&mut self, sclass: SizeClass) -> usize193     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.
free(&mut self, block: usize, sclass: SizeClass)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.
mut_slices(&mut self, block0: usize, block1: usize) -> (&mut [T], &mut [T])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.
realloc( &mut self, block: usize, from_sclass: SizeClass, to_sclass: SizeClass, elems_to_copy: usize, ) -> usize249     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.
new() -> Self272     pub fn new() -> Self {
273         Default::default()
274     }
275 
276     /// Create a new list with the contents initialized from a slice.
from_slice(slice: &[T], pool: &mut ListPool<T>) -> Self277     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.
is_empty(&self) -> bool294     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.
len(&self, pool: &ListPool<T>) -> usize301     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
is_valid(&self, pool: &ListPool<T>) -> bool307     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.
as_slice<'a>(&self, pool: &'a ListPool<T>) -> &'a [T]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.
get(&self, index: usize, pool: &ListPool<T>) -> Option<T>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.
first(&self, pool: &ListPool<T>) -> Option<T>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.
as_mut_slice<'a>(&'a mut self, pool: &'a mut ListPool<T>) -> &'a mut [T]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.
get_mut<'a>(&'a mut self, index: usize, pool: &'a mut ListPool<T>) -> Option<&'a mut T>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.
deep_clone(&self, pool: &mut ListPool<T>) -> Self350     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.
clear(&mut self, pool: &mut ListPool<T>)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()`.
take(&mut self) -> Self383     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.
push(&mut self, element: T, pool: &mut ListPool<T>) -> usize389     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.
grow<'a>(&'a mut self, count: usize, pool: &'a mut ListPool<T>) -> &'a mut [T]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.
from_iter<I>(elements: I, pool: &mut ListPool<T>) -> Self where I: IntoIterator<Item = T>,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.
extend<I>(&mut self, elements: I, pool: &mut ListPool<T>) where I: IntoIterator<Item = T>,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`.
copy_from( &mut self, other: &Self, slice: impl core::ops::RangeBounds<usize>, index: usize, pool: &mut ListPool<T>, )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.
insert(&mut self, index: usize, element: T, pool: &mut ListPool<T>)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.
remove_last(&mut self, len: usize, pool: &mut ListPool<T>)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.
remove(&mut self, index: usize, pool: &mut ListPool<T>)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.
swap_remove(&mut self, index: usize, pool: &mut ListPool<T>)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`.
truncate(&mut self, new_len: usize, pool: &mut ListPool<T>)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.
grow_at(&mut self, index: usize, count: usize, pool: &mut ListPool<T>)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]
size_classes()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]
block_allocator()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]
empty_list()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]
from_slice()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]
push()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]
insert_remove()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]
growing()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]
deep_clone()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]
truncate()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]
copy_from()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]
copy_from_self()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