avian3d/data_structures/stable_vec.rs
1//! A vector data structure that maintains stable indices for its elements.
2//!
3//! # Why Not `slab`?
4//!
5//! The `slab` crate provides a similar `Slab` data structure.
6//! However, its insertion order is not necessarily preserved when elements are removed.
7//! For example, after clearing the slab, the next element might not be inserted at index 0,
8//! but rather it reuses some other slot. This can lead to seemingly non-deterministic behavior
9//! when clearing and repopulating scenes, for example.
10//!
11//! This `StableVec` implementation instead always pushes elements to the first available slot
12//! with the lowest index, ensuring that insertion order is preserved across removals and clear operations.
13//!
14//! # Why Not `stable_vec`?
15//!
16//! The `stable_vec` crate provides a similar `StableVec` data structure.
17//! However, it doesn't actually reuse slots of removed elements, leading to unbounded memory growth
18//! if elements are frequently added and removed. This makes it unsuitable for general-purpose use
19//! for gameplay scenarios.
20//!
21//! This `StableVec` implementation reuses slots of removed elements, using the [`IdPool`] type
22//! to track free indices.
23
24use crate::data_structures::id_pool::IdPool;
25
26/// A [`Vec<T>`]-like collection that maintains stable indices for its elements.
27///
28/// Unlike with a standard [`Vec<T>`], removing elements from a [`StableVec<T>`] is O(1),
29/// and it does not move other elements or invalidate their indices.
30/// This is achieved by internally storing each element as an [`Option<T>`],
31/// and reusing freed slots for new elements.
32///
33/// # Overiew of Important Methods
34///
35/// - [`push`](Self::push) adds a new element and returns its stable index (O(1)).
36/// - [`remove`](Self::remove) removes an element at a given index and returns it (O(1)).
37/// - [`try_remove`](Self::try_remove) attempts to remove an element at a given index, returning `None` if it doesn't exist (O(1)).
38/// - [`get`](Self::get) and [`get_mut`](Self::get_mut) provide access to elements by index (O(1)).
39/// - [`clear`](Self::clear) removes all elements without deallocating memory (O(1)).
40#[derive(Clone, Debug)]
41pub struct StableVec<T> {
42 data: Vec<Option<T>>,
43 indices: IdPool,
44}
45
46impl<T> StableVec<T> {
47 /// Creates a new empty [`StableVec`].
48 #[inline(always)]
49 pub const fn new() -> Self {
50 Self {
51 data: Vec::new(),
52 indices: IdPool::new(),
53 }
54 }
55
56 /// Creates a new [`StableVec`] with the given initial capacity.
57 ///
58 /// This is useful for preallocating space to avoid reallocations.
59 #[inline(always)]
60 pub fn with_capacity(capacity: usize) -> Self {
61 Self {
62 data: Vec::with_capacity(capacity),
63 indices: IdPool::with_capacity(capacity),
64 }
65 }
66
67 /// Pushes a new element to the first available slot, returning its index.
68 ///
69 /// This may reuse a previously freed slot.
70 ///
71 /// # Time Complexity
72 ///
73 /// O(1)
74 #[inline(always)]
75 pub fn push(&mut self, element: T) -> usize {
76 let index = self.indices.alloc() as usize;
77
78 if index >= self.data.len() {
79 self.data.push(Some(element));
80 } else {
81 self.data[index] = Some(element);
82 }
83
84 index
85 }
86
87 /// Returns the next index that will be used for a push.
88 ///
89 /// This index may reuse a previously freed slot.
90 ///
91 /// # Time Complexity
92 ///
93 /// O(1)
94 #[inline(always)]
95 pub fn next_push_index(&self) -> usize {
96 self.indices.next_id() as usize
97 }
98
99 /// Removes the element at the given index, returning it.
100 ///
101 /// # Time Complexity
102 ///
103 /// O(1)
104 ///
105 /// # Panics
106 ///
107 /// Panics if there is no element at the given index.
108 #[inline(always)]
109 pub fn remove(&mut self, index: usize) -> T {
110 self.try_remove(index).unwrap_or_else(|| {
111 panic!("no element at index {} in StableVec::remove", index);
112 })
113 }
114
115 /// Tries to remove the element at the given index, returning it if it existed.
116 ///
117 /// # Time Complexity
118 ///
119 /// O(1)
120 #[inline(always)]
121 pub fn try_remove(&mut self, index: usize) -> Option<T> {
122 if index >= self.data.len() {
123 return None;
124 }
125 let element = self.data[index].take();
126 if element.is_some() {
127 self.indices.free(index as u32);
128 }
129 element
130 }
131
132 /// Removes all elements from the [`StableVec`].
133 ///
134 /// No memory is deallocated, so the capacity remains the same.
135 ///
136 /// # Time Complexity
137 ///
138 /// O(1)
139 #[inline(always)]
140 pub fn clear(&mut self) {
141 self.data.clear();
142 self.indices.clear();
143 }
144
145 /// Returns a reference to the element at the given index, if it exists.
146 ///
147 /// # Time Complexity
148 ///
149 /// O(1)
150 #[inline(always)]
151 pub fn get(&self, index: usize) -> Option<&T> {
152 self.data.get(index)?.as_ref()
153 }
154
155 /// Returns a mutable reference to the element at the given index, if it exists.
156 ///
157 /// # Time Complexity
158 ///
159 /// O(1)
160 #[inline(always)]
161 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
162 self.data.get_mut(index)?.as_mut()
163 }
164
165 /// Returns a reference to the element at the given index without bounds checking.
166 ///
167 /// # Time Complexity
168 ///
169 /// O(1)
170 ///
171 /// # Safety
172 ///
173 /// The caller must ensure that the index is in bounds
174 /// and that there is an element at that index.
175 #[inline(always)]
176 pub unsafe fn get_unchecked(&self, index: usize) -> &T {
177 unsafe { self.data.get_unchecked(index).as_ref().unwrap_unchecked() }
178 }
179
180 /// Returns a mutable reference to the element at the given index without bounds checking.
181 ///
182 /// # Time Complexity
183 ///
184 /// O(1)
185 ///
186 /// # Safety
187 ///
188 /// The caller must ensure that the index is in bounds
189 /// and that there is an element at that index.
190 #[inline(always)]
191 pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
192 unsafe {
193 self.data
194 .get_unchecked_mut(index)
195 .as_mut()
196 .unwrap_unchecked()
197 }
198 }
199
200 /// Returns mutable references to two disjoint elements at the given indices, if they exist.
201 ///
202 /// If the indices are the same, or if either index is out of bounds or has no element,
203 /// `None` is returned.
204 ///
205 /// # Time Complexity
206 ///
207 /// O(1)
208 #[inline(always)]
209 pub fn get_disjoint_mut2(&mut self, index1: usize, index2: usize) -> Option<[&mut T; 2]> {
210 // TODO: Return a `Result`.
211 let [first, second] = self.data.get_disjoint_mut([index1, index2]).ok()?;
212 Some([first.as_mut()?, second.as_mut()?])
213 }
214
215 /// Returns mutable references to two disjoint elements at the given indices without bounds checking.
216 ///
217 /// If the indices are the same, or if either index has no element,
218 /// the behavior is undefined.
219 ///
220 /// # Time Complexity
221 ///
222 /// O(1)
223 ///
224 /// # Safety
225 ///
226 /// The caller must ensure that the indices are disjoint
227 /// and that there are elements at both indices.
228 #[inline(always)]
229 pub unsafe fn get_disjoint_mut_unchecked(
230 &mut self,
231 index1: usize,
232 index2: usize,
233 ) -> [&mut T; 2] {
234 // TODO: Return a `Result`.
235 unsafe {
236 let [first, second] = self.data.get_disjoint_unchecked_mut([index1, index2]);
237 [
238 first.as_mut().unwrap_unchecked(),
239 second.as_mut().unwrap_unchecked(),
240 ]
241 }
242 }
243
244 /// Returns the number of elements in the [`StableVec`].
245 ///
246 /// # Time Complexity
247 ///
248 /// O(1)
249 #[inline(always)]
250 pub fn len(&self) -> usize {
251 self.indices.len()
252 }
253
254 /// Returns `true` if the [`StableVec`] is empty.
255 ///
256 /// # Time Complexity
257 ///
258 /// O(1)
259 #[inline(always)]
260 pub fn is_empty(&self) -> bool {
261 self.len() == 0
262 }
263
264 /// Returns the capacity of the [`StableVec`].
265 ///
266 /// # Time Complexity
267 ///
268 /// O(1)
269 #[inline(always)]
270 pub fn capacity(&self) -> usize {
271 self.data.capacity()
272 }
273
274 /// Returns an iterator over the elements and indices of the [`StableVec`].
275 #[inline(always)]
276 pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
277 self.data
278 .iter()
279 .enumerate()
280 .filter_map(|(i, opt)| opt.as_ref().map(|v| (i, v)))
281 }
282
283 /// Returns a mutable iterator over the elements and indices of the [`StableVec`].
284 #[inline(always)]
285 pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, &mut T)> {
286 self.data
287 .iter_mut()
288 .enumerate()
289 .filter_map(|(i, opt)| opt.as_mut().map(|v| (i, v)))
290 }
291}
292
293impl<T> Default for StableVec<T> {
294 /// Creates a new empty [`StableVec`].
295 #[inline(always)]
296 fn default() -> Self {
297 Self::new()
298 }
299}
300
301impl<T> core::ops::Index<usize> for StableVec<T> {
302 type Output = T;
303
304 /// Returns a reference to the element at the given index.
305 ///
306 /// # Time Complexity
307 ///
308 /// O(1)
309 ///
310 /// # Panics
311 ///
312 /// Panics if there is no element at the given index.
313 #[inline(always)]
314 fn index(&self, index: usize) -> &Self::Output {
315 self.get(index).unwrap_or_else(|| {
316 panic!("no element at index {} in StableVec::index", index);
317 })
318 }
319}
320
321impl<T> core::ops::IndexMut<usize> for StableVec<T> {
322 /// Returns a mutable reference to the element at the given index.
323 ///
324 /// # Time Complexity
325 ///
326 /// O(1)
327 ///
328 /// # Panics
329 ///
330 /// Panics if there is no element at the given index.
331 #[inline(always)]
332 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
333 self.get_mut(index).unwrap_or_else(|| {
334 panic!("no element at index {} in StableVec::index_mut", index);
335 })
336 }
337}
338
339impl<T> IntoIterator for StableVec<T> {
340 type Item = T;
341 type IntoIter = StableVecIntoIterator<T>;
342
343 #[inline(always)]
344 fn into_iter(self) -> Self::IntoIter {
345 StableVecIntoIterator {
346 inner: self.data.into_iter(),
347 }
348 }
349}
350
351/// An iterator over the elements of a [`StableVec`].
352pub struct StableVecIntoIterator<T> {
353 inner: alloc::vec::IntoIter<Option<T>>,
354}
355
356impl<T> Iterator for StableVecIntoIterator<T> {
357 type Item = T;
358
359 #[inline(always)]
360 fn next(&mut self) -> Option<Self::Item> {
361 self.inner.by_ref().flatten().next()
362 }
363}
364
365impl<T> DoubleEndedIterator for StableVecIntoIterator<T> {
366 #[inline(always)]
367 fn next_back(&mut self) -> Option<Self::Item> {
368 self.inner.by_ref().flatten().next_back()
369 }
370}
371
372impl<T> core::iter::FusedIterator for StableVecIntoIterator<T> {}
373
374#[cfg(test)]
375mod tests {
376 use super::StableVec;
377
378 #[test]
379 fn test_stable_vec_push_remove() {
380 let mut sv = StableVec::new();
381 let idx1 = sv.push(10);
382 let idx2 = sv.push(20);
383
384 assert_eq!(sv.len(), 2);
385 assert_eq!(sv[idx1], 10);
386 assert_eq!(sv[idx2], 20);
387
388 let val = sv.remove(idx1);
389 assert_eq!(val, 10);
390 assert_eq!(sv.len(), 1);
391 assert!(sv.get(idx1).is_none());
392
393 let idx3 = sv.push(30);
394 assert_eq!(idx3, idx1); // Reused index
395 assert_eq!(sv[idx3], 30);
396 }
397
398 #[test]
399 fn test_stable_vec_clear() {
400 let mut sv = StableVec::new();
401 sv.push(1);
402 sv.push(2);
403 sv.clear();
404 assert_eq!(sv.len(), 0);
405 }
406
407 #[test]
408 fn test_stable_vec_iter() {
409 let mut sv = StableVec::new();
410 sv.push(1);
411 sv.push(2);
412 sv.push(3);
413
414 let collected: Vec<_> = sv.into_iter().collect();
415 assert_eq!(collected, vec![1, 2, 3]);
416 }
417}