obj_pool/lib.rs
1//! A simple object pool.
2//!
3//! `ObjPool<T>` is basically just a `Vec<Option<T>>`, which allows you to:
4//!
5//! * Insert an object (reuse an existing `None` element, or append to the end) and get an `ObjId`
6//! in return.
7//! * Remove object with a specified `ObjId`.
8//! * Access object with a specified `ObjId`.
9//! * Convert `ObjId` to index and back for specified `ObjPool`.
10//!
11//! # Limitations:
12//!
13//! * `ObjId` is always 32-bit long.
14//!
15//! # Examples
16//!
17//! Some data structures built using `ObjPool<T>`:
18//!
19//! * [Doubly linked list](https://github.com/artemshein/obj-pool/blob/master/examples/linked_list.rs)
20//! * [Splay tree](https://github.com/artemshein/obj-pool/blob/master/examples/splay_tree.rs)
21use std::{
22 fmt, iter, mem,
23 num::{NonZeroU32, ParseIntError},
24 ops::{Index, IndexMut},
25 ptr,
26 str::FromStr,
27 vec,
28};
29
30use std::ops::Deref;
31use std::slice;
32use unreachable::unreachable;
33
34#[cfg(feature = "serde_support")]
35use serde::{Deserialize, Serialize};
36
37mod par;
38pub use par::*;
39
40/// A slot, which is either vacant or occupied.
41///
42/// Vacant slots in object pool are linked together into a singly linked list. This allows the object pool to
43/// efficiently find a vacant slot before inserting a new object, or reclaiming a slot after
44/// removing an object.
45#[derive(Clone)]
46enum Slot<T> {
47 /// Vacant slot, containing index to the next slot in the linked list.
48 Vacant(u32),
49
50 /// Occupied slot, containing a value.
51 Occupied(T),
52}
53
54/// An id of the object in an `ObjPool`.
55///
56/// In release it is basically just an index in the underlying vector, but in debug it's an `index` +
57/// `ObjPool`-specific `offset`. This is made to be able to check `ObjId` if it's from the same
58/// `ObjPool` we are trying to get an object from.
59#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
60#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
61pub struct ObjId(pub NonZeroU32);
62
63impl ObjId {
64 pub fn from_index(index: u32) -> Self {
65 debug_assert!(index < u32::MAX, "index out of range");
66 // SAFETY: index + 1 is non-zero for any index < u32::MAX, which the
67 // debug assertion above guarantees. Using unchecked here makes the
68 // function side-effect-free in release builds so the compiler can
69 // eliminate ObjId construction when the result is unused (e.g. in
70 // iterator benchmarks that discard the key with `_`).
71 Self(unsafe { NonZeroU32::new_unchecked(index + 1) })
72 }
73
74 pub const fn into_index(self) -> u32 {
75 self.0.get() - 1
76 }
77}
78
79impl std::fmt::Display for ObjId {
80 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
81 self.0.fmt(f)
82 }
83}
84
85impl FromStr for ObjId {
86 type Err = ParseIntError;
87
88 fn from_str(s: &str) -> Result<Self, Self::Err> {
89 Ok(ObjId(s.parse::<NonZeroU32>()?))
90 }
91}
92
93impl Deref for ObjId {
94 type Target = NonZeroU32;
95
96 fn deref(&self) -> &Self::Target {
97 &self.0
98 }
99}
100
101impl From<NonZeroU32> for ObjId {
102 fn from(v: NonZeroU32) -> ObjId {
103 ObjId(v)
104 }
105}
106
107/// An object pool.
108///
109/// `ObjPool<T>` holds an array of slots for storing objects.
110/// Every slot is always in one of two states: occupied or vacant.
111///
112/// Essentially, this is equivalent to `Vec<Option<T>>`.
113///
114/// # Insert and remove
115///
116/// When inserting a new object into object pool, a vacant slot is found and then the object is placed
117/// into the slot. If there are no vacant slots, the array is reallocated with bigger capacity.
118/// The cost of insertion is amortized `O(1)`.
119///
120/// When removing an object, the slot containing it is marked as vacant and the object is returned.
121/// The cost of removal is `O(1)`.
122///
123/// ```
124/// use obj_pool::ObjPool;
125///
126/// let mut obj_pool = ObjPool::new();
127/// let a = obj_pool.insert(10);
128/// assert_eq!(a.into_index(), 0);
129/// let b = obj_pool.insert(20);
130/// assert_eq!(b.into_index(), 1);
131///
132/// assert_ne!(a, b); // ids are not the same
133///
134/// assert_eq!(obj_pool.remove(a), Some(10));
135/// assert_eq!(obj_pool.get(a), None); // there is no object with this `ObjId` anymore
136///
137/// assert_eq!(obj_pool.insert(30), a); // slot is reused, got the same `ObjId`
138/// ```
139///
140/// # Indexing
141///
142/// You can also access objects in an object pool by `ObjId`.
143/// However, accessing an object with invalid `ObjId` will result in panic.
144///
145/// ```
146/// use obj_pool::ObjPool;
147///
148/// let mut obj_pool = ObjPool::new();
149/// let a = obj_pool.insert(10);
150/// let b = obj_pool.insert(20);
151///
152/// assert_eq!(obj_pool[a], 10);
153/// assert_eq!(obj_pool[b], 20);
154///
155/// obj_pool[a] += obj_pool[b];
156/// assert_eq!(obj_pool[a], 30);
157/// ```
158///
159/// To access slots without fear of panicking, use `get` and `get_mut`, which return `Option`s.
160pub struct ObjPool<T> {
161 /// Slots in which objects are stored.
162 slots: Vec<Slot<T>>,
163
164 /// Number of occupied slots in the object pool.
165 len: u32,
166
167 /// Index of the first vacant slot in the linked list.
168 head: u32,
169}
170
171impl<T> AsRef<ObjPool<T>> for ObjPool<T> {
172 fn as_ref(&self) -> &ObjPool<T> {
173 self
174 }
175}
176
177impl<T> AsMut<ObjPool<T>> for ObjPool<T> {
178 fn as_mut(&mut self) -> &mut ObjPool<T> {
179 self
180 }
181}
182
183impl<T> ObjPool<T> {
184 /// Constructs a new, empty object pool.
185 ///
186 /// The object pool will not allocate until objects are inserted into it.
187 ///
188 /// # Examples
189 ///
190 /// ```
191 /// use obj_pool::ObjPool;
192 ///
193 /// let mut obj_pool: ObjPool<i32> = ObjPool::new();
194 /// ```
195 #[inline]
196 pub const fn new() -> Self {
197 ObjPool {
198 slots: Vec::new(),
199 len: 0,
200 head: u32::MAX,
201 }
202 }
203
204 /// Get an index in the `ObjPool` for the given `ObjId`.
205 #[inline]
206 pub const fn obj_id_to_index(obj_id: ObjId) -> u32 {
207 obj_id.into_index()
208 }
209
210 /// Make an `ObjId` from an index in this `ObjPool`.
211 #[inline]
212 pub fn index_to_obj_id(index: u32) -> ObjId {
213 ObjId::from_index(index)
214 }
215
216 /// Constructs a new, empty object pool with the specified capacity (number of slots).
217 ///
218 /// The object pool will be able to hold exactly `capacity` objects without reallocating.
219 /// If `capacity` is 0, the object pool will not allocate.
220 ///
221 /// # Examples
222 ///
223 /// ```
224 /// use obj_pool::ObjPool;
225 ///
226 /// let mut obj_pool = ObjPool::with_capacity(10);
227 ///
228 /// assert_eq!(obj_pool.len(), 0);
229 /// assert_eq!(obj_pool.capacity(), 10);
230 ///
231 /// // These inserts are done without reallocating...
232 /// for i in 0..10 {
233 /// obj_pool.insert(i);
234 /// }
235 /// assert_eq!(obj_pool.capacity(), 10);
236 ///
237 /// // ... but this one will reallocate.
238 /// obj_pool.insert(11);
239 /// assert!(obj_pool.capacity() > 10);
240 /// ```
241 #[inline]
242 pub fn with_capacity(cap: usize) -> Self {
243 ObjPool {
244 slots: Vec::with_capacity(cap),
245 len: 0,
246 head: u32::MAX,
247 }
248 }
249
250 /// Returns the number of slots in the object pool.
251 ///
252 /// # Examples
253 ///
254 /// ```
255 /// use obj_pool::ObjPool;
256 ///
257 /// let obj_pool: ObjPool<i32> = ObjPool::with_capacity(10);
258 /// assert_eq!(obj_pool.capacity(), 10);
259 /// ```
260 #[inline]
261 pub fn capacity(&self) -> usize {
262 self.slots.capacity()
263 }
264
265 /// Returns the number of occupied slots in the object pool.
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// use obj_pool::ObjPool;
271 ///
272 /// let mut obj_pool = ObjPool::new();
273 /// assert_eq!(obj_pool.len(), 0);
274 ///
275 /// for i in 0..10 {
276 /// obj_pool.insert(());
277 /// assert_eq!(obj_pool.len(), i + 1);
278 /// }
279 /// ```
280 #[inline]
281 pub fn len(&self) -> u32 {
282 self.len
283 }
284
285 /// Returns `true` if all slots are vacant.
286 ///
287 /// # Examples
288 ///
289 /// ```
290 /// use obj_pool::ObjPool;
291 ///
292 /// let mut obj_pool = ObjPool::new();
293 /// assert!(obj_pool.is_empty());
294 ///
295 /// obj_pool.insert(1);
296 /// assert!(!obj_pool.is_empty());
297 /// ```
298 #[inline]
299 pub fn is_empty(&self) -> bool {
300 self.len == 0
301 }
302
303 /// Returns the `ObjId` of the next inserted object if no other
304 /// mutating calls take place in between.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// use obj_pool::ObjPool;
310 ///
311 /// let mut obj_pool = ObjPool::new();
312 ///
313 /// let a = obj_pool.next_vacant();
314 /// let b = obj_pool.insert(1);
315 /// assert_eq!(a, b);
316 /// let c = obj_pool.next_vacant();
317 /// let d = obj_pool.insert(2);
318 /// assert_eq!(c, d);
319 /// ```
320 #[inline]
321 pub fn next_vacant(&mut self) -> ObjId {
322 Self::index_to_obj_id(if self.head == u32::MAX {
323 self.len
324 } else {
325 self.head
326 })
327 }
328
329 /// Inserts an object into the object pool and returns the `ObjId` of this object.
330 /// The object pool will reallocate if it's full.
331 ///
332 /// # Examples
333 ///
334 /// ```
335 /// use obj_pool::ObjPool;
336 ///
337 /// let mut obj_pool = ObjPool::new();
338 ///
339 /// let a = obj_pool.insert(1);
340 /// let b = obj_pool.insert(2);
341 /// assert!(a != b);
342 /// ```
343 pub fn insert(&mut self, object: T) -> ObjId {
344 self.len += 1;
345
346 if self.head == u32::MAX {
347 self.slots.push(Slot::Occupied(object));
348 Self::index_to_obj_id(self.len - 1)
349 } else {
350 let index = self.head;
351 match self.slots[index as usize] {
352 Slot::Vacant(next) => {
353 self.head = next;
354 self.slots[index as usize] = Slot::Occupied(object);
355 }
356 Slot::Occupied(_) => unreachable!(),
357 }
358 Self::index_to_obj_id(index)
359 }
360 }
361
362 /// Removes the object stored by `ObjId` from the object pool and returns it.
363 ///
364 /// `None` is returned in case the there is no object with such an `ObjId`.
365 ///
366 /// # Examples
367 ///
368 /// ```
369 /// use obj_pool::ObjPool;
370 ///
371 /// let mut obj_pool = ObjPool::new();
372 /// let a = obj_pool.insert("hello");
373 ///
374 /// assert_eq!(obj_pool.len(), 1);
375 /// assert_eq!(obj_pool.remove(a), Some("hello"));
376 ///
377 /// assert_eq!(obj_pool.len(), 0);
378 /// assert_eq!(obj_pool.remove(a), None);
379 /// ```
380 pub fn remove(&mut self, obj_id: ObjId) -> Option<T> {
381 let index = Self::obj_id_to_index(obj_id);
382 match self.slots.get_mut(index as usize) {
383 None => None,
384 Some(&mut Slot::Vacant(_)) => None,
385 Some(slot @ &mut Slot::Occupied(_)) => {
386 if let Slot::Occupied(object) = mem::replace(slot, Slot::Vacant(self.head)) {
387 self.head = index;
388 self.len -= 1;
389 Some(object)
390 } else {
391 unreachable!();
392 }
393 }
394 }
395 }
396
397 /// Clears the object pool, removing and dropping all objects it holds. Keeps the allocated memory
398 /// for reuse.
399 ///
400 /// # Examples
401 ///
402 /// ```
403 /// use obj_pool::ObjPool;
404 ///
405 /// let mut obj_pool = ObjPool::new();
406 /// for i in 0..10 {
407 /// obj_pool.insert(i);
408 /// }
409 ///
410 /// assert_eq!(obj_pool.len(), 10);
411 /// obj_pool.clear();
412 /// assert_eq!(obj_pool.len(), 0);
413 /// ```
414 #[inline]
415 pub fn clear(&mut self) {
416 self.slots.clear();
417 self.len = 0;
418 self.head = u32::MAX;
419 }
420
421 /// Returns a reference to the object by its `ObjId`.
422 ///
423 /// If object is not found with given `obj_id`, `None` is returned.
424 ///
425 /// # Examples
426 ///
427 /// ```
428 /// use obj_pool::ObjPool;
429 ///
430 /// let mut obj_pool = ObjPool::new();
431 /// let obj_id = obj_pool.insert("hello");
432 ///
433 /// assert_eq!(obj_pool.get(obj_id), Some(&"hello"));
434 /// obj_pool.remove(obj_id);
435 /// assert_eq!(obj_pool.get(obj_id), None);
436 /// ```
437 pub fn get(&self, obj_id: ObjId) -> Option<&T> {
438 let index = Self::obj_id_to_index(obj_id) as usize;
439 match self.slots.get(index) {
440 None => None,
441 Some(&Slot::Vacant(_)) => None,
442 Some(Slot::Occupied(object)) => Some(object),
443 }
444 }
445
446 /// Returns a mutable reference to the object by its `ObjId`.
447 ///
448 /// If object can't be found, `None` is returned.
449 ///
450 /// # Examples
451 ///
452 /// ```
453 /// use obj_pool::ObjPool;
454 ///
455 /// let mut obj_pool = ObjPool::new();
456 /// let obj_id = obj_pool.insert(7);
457 ///
458 /// assert_eq!(obj_pool.get_mut(obj_id), Some(&mut 7));
459 /// *obj_pool.get_mut(obj_id).unwrap() *= 10;
460 /// assert_eq!(obj_pool.get_mut(obj_id), Some(&mut 70));
461 /// ```
462 #[inline]
463 pub fn get_mut(&mut self, obj_id: ObjId) -> Option<&mut T> {
464 let index = Self::obj_id_to_index(obj_id) as usize;
465 match self.slots.get_mut(index) {
466 None => None,
467 Some(&mut Slot::Vacant(_)) => None,
468 Some(&mut Slot::Occupied(ref mut object)) => Some(object),
469 }
470 }
471
472 /// Returns a reference to the object by its `ObjId`.
473 ///
474 /// # Safety
475 ///
476 /// Behavior is undefined if object can't be found.
477 ///
478 /// # Examples
479 ///
480 /// ```
481 /// use obj_pool::ObjPool;
482 ///
483 /// let mut obj_pool = ObjPool::new();
484 /// let obj_id = obj_pool.insert("hello");
485 ///
486 /// unsafe { assert_eq!(&*obj_pool.get_unchecked(obj_id), &"hello") }
487 /// ```
488 pub unsafe fn get_unchecked(&self, obj_id: ObjId) -> &T {
489 match self.slots.get(Self::obj_id_to_index(obj_id) as usize) {
490 None => unsafe { unreachable() },
491 Some(Slot::Vacant(_)) => unsafe { unreachable() },
492 Some(Slot::Occupied(object)) => object,
493 }
494 }
495
496 /// Returns a mutable reference to the object by its `ObjId`.
497 ///
498 /// # Safety
499 ///
500 /// Behavior is undefined if object can't be found.
501 ///
502 /// # Examples
503 ///
504 /// ```
505 /// use obj_pool::ObjPool;
506 ///
507 /// let mut obj_pool = ObjPool::new();
508 /// let obj_id = obj_pool.insert("hello");
509 ///
510 /// unsafe { assert_eq!(&*obj_pool.get_unchecked_mut(obj_id), &"hello") }
511 /// ```
512 pub unsafe fn get_unchecked_mut(&mut self, obj_id: ObjId) -> &mut T {
513 let index = Self::obj_id_to_index(obj_id) as usize;
514 match self.slots.get_mut(index) {
515 Some(&mut Slot::Vacant(_)) => unsafe { unreachable() },
516 Some(&mut Slot::Occupied(ref mut object)) => object,
517 _ => unsafe { unreachable() },
518 }
519 }
520
521 /// Swaps two objects in the object pool.
522 ///
523 /// The two `ObjId`s are `a` and `b`.
524 ///
525 /// # Panics
526 ///
527 /// Panics if any of the `ObjId`s is invalid.
528 ///
529 /// # Examples
530 ///
531 /// ```
532 /// use obj_pool::ObjPool;
533 ///
534 /// let mut obj_pool = ObjPool::new();
535 /// let a = obj_pool.insert(7);
536 /// let b = obj_pool.insert(8);
537 ///
538 /// obj_pool.swap(a, b);
539 /// assert_eq!(obj_pool.get(a), Some(&8));
540 /// assert_eq!(obj_pool.get(b), Some(&7));
541 /// ```
542 #[inline]
543 pub fn swap(&mut self, a: ObjId, b: ObjId) {
544 unsafe {
545 let fst = self.get_mut(a).unwrap() as *mut _;
546 let snd = self.get_mut(b).unwrap() as *mut _;
547 if a != b {
548 ptr::swap(fst, snd);
549 }
550 }
551 }
552
553 /// Reserves capacity for at least `additional` more objects to be inserted. The object pool may
554 /// reserve more space to avoid frequent reallocations.
555 ///
556 /// # Panics
557 ///
558 /// Panics if the new capacity overflows `u32`.
559 ///
560 /// # Examples
561 ///
562 /// ```
563 /// use obj_pool::ObjPool;
564 ///
565 /// let mut obj_pool = ObjPool::new();
566 /// obj_pool.insert("hello");
567 ///
568 /// obj_pool.reserve(10);
569 /// assert!(obj_pool.capacity() >= 11);
570 /// ```
571 pub fn reserve(&mut self, additional: u32) {
572 let vacant = self.slots.len() as u32 - self.len;
573 if additional > vacant {
574 self.slots.reserve((additional - vacant) as usize);
575 }
576 }
577
578 /// Reserves the minimum capacity for exactly `additional` more objects to be inserted.
579 ///
580 /// Note that the allocator may give the object pool more space than it requests.
581 ///
582 /// # Panics
583 ///
584 /// Panics if the new capacity overflows `u32`.
585 ///
586 /// # Examples
587 ///
588 /// ```
589 /// use obj_pool::ObjPool;
590 ///
591 /// let mut obj_pool = ObjPool::new();
592 /// obj_pool.insert("hello");
593 ///
594 /// obj_pool.reserve_exact(10);
595 /// assert!(obj_pool.capacity() >= 11);
596 /// ```
597 pub fn reserve_exact(&mut self, additional: u32) {
598 let vacant = self.slots.len() as u32 - self.len;
599 if additional > vacant {
600 self.slots.reserve_exact((additional - vacant) as usize);
601 }
602 }
603
604 /// Returns an iterator over occupied slots.
605 ///
606 /// # Examples
607 ///
608 /// ```
609 /// use obj_pool::ObjPool;
610 ///
611 /// let mut obj_pool = ObjPool::new();
612 /// obj_pool.insert(1);
613 /// obj_pool.insert(2);
614 /// obj_pool.insert(4);
615 ///
616 /// let mut iterator = obj_pool.iter();
617 /// assert_eq!(iterator.next(), Some((ObjPool::<usize>::index_to_obj_id(0), &1)));
618 /// assert_eq!(iterator.next(), Some((ObjPool::<usize>::index_to_obj_id(1), &2)));
619 /// assert_eq!(iterator.next(), Some((ObjPool::<usize>::index_to_obj_id(2), &4)));
620 /// ```
621 #[inline]
622 pub fn iter(&self) -> Iter<'_, T> {
623 Iter {
624 len: self.len as usize,
625 slots: self.slots.iter().enumerate(),
626 }
627 }
628
629 /// Returns an iterator that returns mutable references to objects.
630 ///
631 /// # Examples
632 ///
633 /// ```
634 /// use obj_pool::ObjPool;
635 ///
636 /// let mut obj_pool = ObjPool::new();
637 /// obj_pool.insert("zero".to_string());
638 /// obj_pool.insert("one".to_string());
639 /// obj_pool.insert("two".to_string());
640 ///
641 /// for (obj_id, object) in obj_pool.iter_mut() {
642 /// *object = obj_id.into_index().to_string() + " " + object;
643 /// }
644 ///
645 /// let mut iterator = obj_pool.iter();
646 /// assert_eq!(iterator.next(), Some((ObjPool::<String>::index_to_obj_id(0), &"0 zero".to_string())));
647 /// assert_eq!(iterator.next(), Some((ObjPool::<String>::index_to_obj_id(1), &"1 one".to_string())));
648 /// assert_eq!(iterator.next(), Some((ObjPool::<String>::index_to_obj_id(2), &"2 two".to_string())));
649 /// ```
650 #[inline]
651 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
652 IterMut {
653 len: self.len as usize,
654 slots: self.slots.iter_mut().enumerate(),
655 }
656 }
657
658 /// Shrinks the capacity of the object pool as much as possible.
659 ///
660 /// It will drop down as close as possible to the length but the allocator may still inform
661 /// the object pool that there is space for a few more elements.
662 ///
663 /// # Examples
664 ///
665 /// ```
666 /// use obj_pool::ObjPool;
667 ///
668 /// let mut obj_pool = ObjPool::with_capacity(10);
669 /// obj_pool.insert("first".to_string());
670 /// obj_pool.insert("second".to_string());
671 /// obj_pool.insert("third".to_string());
672 /// assert_eq!(obj_pool.capacity(), 10);
673 /// obj_pool.shrink_to_fit();
674 /// assert!(obj_pool.capacity() >= 3);
675 /// ```
676 pub fn shrink_to_fit(&mut self) {
677 self.slots.shrink_to_fit();
678 }
679}
680
681impl<T> fmt::Debug for ObjPool<T> {
682 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
683 write!(f, "ObjPool {{ ... }}")
684 }
685}
686
687impl<T> Index<ObjId> for ObjPool<T> {
688 type Output = T;
689
690 #[inline]
691 fn index(&self, obj_id: ObjId) -> &T {
692 self.get(obj_id).expect("object not found")
693 }
694}
695
696impl<T> IndexMut<ObjId> for ObjPool<T> {
697 #[inline]
698 fn index_mut(&mut self, obj_id: ObjId) -> &mut T {
699 self.get_mut(obj_id).expect("object not found")
700 }
701}
702
703impl<T> Default for ObjPool<T> {
704 fn default() -> Self {
705 ObjPool::new()
706 }
707}
708
709impl<T: Clone> Clone for ObjPool<T> {
710 fn clone(&self) -> Self {
711 ObjPool {
712 slots: self.slots.clone(),
713 len: self.len,
714 head: self.head,
715 }
716 }
717}
718
719/// An iterator over the occupied slots in a `ObjPool`.
720pub struct IntoIter<T> {
721 slots: iter::Enumerate<vec::IntoIter<Slot<T>>>,
722 len: usize,
723}
724
725impl<T> IntoIter<T> {
726 #[inline]
727 pub const fn obj_id_to_index(obj_id: ObjId) -> u32 {
728 obj_id.into_index()
729 }
730
731 #[inline]
732 pub fn index_to_obj_id(index: u32) -> ObjId {
733 ObjId::from_index(index)
734 }
735}
736
737impl<T> Iterator for IntoIter<T> {
738 type Item = (ObjId, T);
739
740 #[inline]
741 fn next(&mut self) -> Option<Self::Item> {
742 for (index, slot) in self.slots.by_ref() {
743 if let Slot::Occupied(object) = slot {
744 self.len -= 1;
745 return Some((Self::index_to_obj_id(index as u32), object));
746 }
747 }
748 None
749 }
750
751 fn size_hint(&self) -> (usize, Option<usize>) {
752 (self.len, Some(self.len))
753 }
754}
755
756impl<T> ExactSizeIterator for IntoIter<T> {
757 fn len(&self) -> usize {
758 self.len
759 }
760}
761
762impl<T> iter::FusedIterator for IntoIter<T> {}
763
764impl<T> IntoIterator for ObjPool<T> {
765 type Item = (ObjId, T);
766 type IntoIter = IntoIter<T>;
767
768 #[inline]
769 fn into_iter(self) -> Self::IntoIter {
770 IntoIter {
771 len: self.len as usize,
772 slots: self.slots.into_iter().enumerate(),
773 }
774 }
775}
776
777impl<T> iter::FromIterator<T> for ObjPool<T> {
778 fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> ObjPool<T> {
779 let iter = iter.into_iter();
780 let mut obj_pool = ObjPool::with_capacity(iter.size_hint().0);
781 for i in iter {
782 obj_pool.insert(i);
783 }
784 obj_pool
785 }
786}
787
788impl<T> fmt::Debug for IntoIter<T> {
789 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
790 write!(f, "IntoIter {{ ... }}")
791 }
792}
793
794/// An iterator over references to the occupied slots in a `ObjPool`.
795pub struct Iter<'a, T: 'a> {
796 slots: iter::Enumerate<slice::Iter<'a, Slot<T>>>,
797 len: usize,
798}
799
800impl<'a, T: 'a> Iter<'a, T> {
801 #[inline]
802 pub fn index_to_obj_id(index: u32) -> ObjId {
803 ObjId::from_index(index)
804 }
805}
806
807impl<'a, T> Iterator for Iter<'a, T> {
808 type Item = (ObjId, &'a T);
809
810 #[inline]
811 fn next(&mut self) -> Option<Self::Item> {
812 for (index, slot) in self.slots.by_ref() {
813 if let Slot::Occupied(ref object) = *slot {
814 self.len -= 1;
815 return Some((Self::index_to_obj_id(index as u32), object));
816 }
817 }
818 None
819 }
820
821 fn size_hint(&self) -> (usize, Option<usize>) {
822 (self.len, Some(self.len))
823 }
824}
825
826impl<T> ExactSizeIterator for Iter<'_, T> {
827 fn len(&self) -> usize {
828 self.len
829 }
830}
831
832impl<T> iter::FusedIterator for Iter<'_, T> {}
833
834impl<'a, T> IntoIterator for &'a ObjPool<T> {
835 type Item = (ObjId, &'a T);
836 type IntoIter = Iter<'a, T>;
837
838 #[inline]
839 fn into_iter(self) -> Self::IntoIter {
840 self.iter()
841 }
842}
843
844impl<'a, T> fmt::Debug for Iter<'a, T> {
845 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
846 write!(f, "Iter {{ ... }}")
847 }
848}
849
850/// An iterator over mutable references to the occupied slots in a `Arena`.
851pub struct IterMut<'a, T: 'a> {
852 slots: iter::Enumerate<slice::IterMut<'a, Slot<T>>>,
853 len: usize,
854}
855
856impl<'a, T: 'a> IterMut<'a, T> {
857 #[inline]
858 pub const fn obj_id_to_index(obj_id: ObjId) -> u32 {
859 obj_id.into_index()
860 }
861
862 #[inline]
863 pub fn index_to_obj_id(index: u32) -> ObjId {
864 ObjId::from_index(index)
865 }
866}
867
868impl<'a, T> Iterator for IterMut<'a, T> {
869 type Item = (ObjId, &'a mut T);
870
871 #[inline]
872 fn next(&mut self) -> Option<Self::Item> {
873 for (index, slot) in self.slots.by_ref() {
874 if let Slot::Occupied(ref mut object) = *slot {
875 self.len -= 1;
876 return Some((Self::index_to_obj_id(index as u32), object));
877 }
878 }
879 None
880 }
881
882 fn size_hint(&self) -> (usize, Option<usize>) {
883 (self.len, Some(self.len))
884 }
885}
886
887impl<T> ExactSizeIterator for IterMut<'_, T> {
888 fn len(&self) -> usize {
889 self.len
890 }
891}
892
893impl<T> iter::FusedIterator for IterMut<'_, T> {}
894
895impl<'a, T> IntoIterator for &'a mut ObjPool<T> {
896 type Item = (ObjId, &'a mut T);
897 type IntoIter = IterMut<'a, T>;
898
899 #[inline]
900 fn into_iter(self) -> Self::IntoIter {
901 self.iter_mut()
902 }
903}
904
905impl<'a, T> fmt::Debug for IterMut<'a, T> {
906 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
907 write!(f, "IterMut {{ ... }}")
908 }
909}
910
911#[cfg(test)]
912mod tests {
913 use super::*;
914
915 #[test]
916 fn new() {
917 let obj_pool = ObjPool::<i32>::new();
918 assert!(obj_pool.is_empty());
919 assert_eq!(obj_pool.len(), 0);
920 assert_eq!(obj_pool.capacity(), 0);
921 }
922
923 #[test]
924 fn insert() {
925 let mut obj_pool = ObjPool::new();
926
927 for i in 0..10 {
928 let a = obj_pool.insert(i * 10);
929 assert_eq!(obj_pool[a], i * 10);
930 }
931 assert!(!obj_pool.is_empty());
932 assert_eq!(obj_pool.len(), 10);
933 }
934
935 #[test]
936 fn with_capacity() {
937 let mut obj_pool = ObjPool::with_capacity(10);
938 assert_eq!(obj_pool.capacity(), 10);
939
940 for _ in 0..10 {
941 obj_pool.insert(());
942 }
943 assert_eq!(obj_pool.len(), 10);
944 assert_eq!(obj_pool.capacity(), 10);
945
946 obj_pool.insert(());
947 assert_eq!(obj_pool.len(), 11);
948 assert!(obj_pool.capacity() > 10);
949 }
950
951 #[test]
952 fn remove() {
953 let mut obj_pool = ObjPool::new();
954
955 let a = obj_pool.insert(0);
956 let b = obj_pool.insert(10);
957 let c = obj_pool.insert(20);
958 obj_pool.insert(30);
959 assert_eq!(obj_pool.len(), 4);
960
961 assert_eq!(obj_pool.remove(b), Some(10));
962 assert_eq!(obj_pool.remove(c), Some(20));
963 assert_eq!(obj_pool.len(), 2);
964
965 obj_pool.insert(-1);
966 obj_pool.insert(-1);
967 assert_eq!(obj_pool.len(), 4);
968
969 assert_eq!(obj_pool.remove(a), Some(0));
970 obj_pool.insert(-1);
971 assert_eq!(obj_pool.len(), 4);
972
973 obj_pool.insert(400);
974 assert_eq!(obj_pool.len(), 5);
975 }
976
977 #[test]
978 fn clear() {
979 let mut obj_pool = ObjPool::new();
980 obj_pool.insert(10);
981 obj_pool.insert(20);
982
983 assert!(!obj_pool.is_empty());
984 assert_eq!(obj_pool.len(), 2);
985
986 let cap = obj_pool.capacity();
987 obj_pool.clear();
988
989 assert!(obj_pool.is_empty());
990 assert_eq!(obj_pool.len(), 0);
991 assert_eq!(obj_pool.capacity(), cap);
992 }
993
994 #[test]
995 fn indexing() {
996 let mut obj_pool = ObjPool::new();
997
998 let a = obj_pool.insert(10);
999 let b = obj_pool.insert(20);
1000 let c = obj_pool.insert(30);
1001
1002 obj_pool[b] += obj_pool[c];
1003 assert_eq!(obj_pool[a], 10);
1004 assert_eq!(obj_pool[b], 50);
1005 assert_eq!(obj_pool[c], 30);
1006 }
1007
1008 #[test]
1009 #[should_panic]
1010 fn indexing_vacant() {
1011 let mut obj_pool = ObjPool::new();
1012
1013 let _ = obj_pool.insert(10);
1014 let b = obj_pool.insert(20);
1015 let _ = obj_pool.insert(30);
1016
1017 obj_pool.remove(b);
1018 obj_pool[b];
1019 }
1020
1021 #[test]
1022 #[should_panic]
1023 fn invalid_indexing() {
1024 let mut obj_pool = ObjPool::new();
1025
1026 obj_pool.insert(10);
1027 obj_pool.insert(20);
1028 let a = obj_pool.insert(30);
1029 obj_pool.remove(a);
1030
1031 obj_pool[a];
1032 }
1033
1034 #[test]
1035 fn get() {
1036 let mut obj_pool = ObjPool::new();
1037
1038 let a = obj_pool.insert(10);
1039 let b = obj_pool.insert(20);
1040 let c = obj_pool.insert(30);
1041
1042 *obj_pool.get_mut(b).unwrap() += *obj_pool.get(c).unwrap();
1043 assert_eq!(obj_pool.get(a), Some(&10));
1044 assert_eq!(obj_pool.get(b), Some(&50));
1045 assert_eq!(obj_pool.get(c), Some(&30));
1046
1047 obj_pool.remove(b);
1048 assert_eq!(obj_pool.get(b), None);
1049 assert_eq!(obj_pool.get_mut(b), None);
1050 }
1051
1052 #[test]
1053 fn reserve() {
1054 let mut obj_pool = ObjPool::new();
1055 obj_pool.insert(1);
1056 obj_pool.insert(2);
1057
1058 obj_pool.reserve(10);
1059 assert!(obj_pool.capacity() >= 11);
1060 }
1061
1062 #[test]
1063 fn reserve_exact() {
1064 let mut obj_pool = ObjPool::new();
1065 obj_pool.insert(1);
1066 obj_pool.insert(2);
1067 obj_pool.reserve(10);
1068 assert!(obj_pool.capacity() >= 11);
1069 }
1070
1071 #[test]
1072 fn iter() {
1073 let mut arena = ObjPool::new();
1074 let a = arena.insert(10);
1075 let b = arena.insert(20);
1076 let c = arena.insert(30);
1077 let d = arena.insert(40);
1078
1079 arena.remove(b);
1080
1081 let mut it = arena.iter();
1082 assert_eq!(it.next(), Some((a, &10)));
1083 assert_eq!(it.next(), Some((c, &30)));
1084 assert_eq!(it.next(), Some((d, &40)));
1085 assert_eq!(it.next(), None);
1086 }
1087
1088 #[test]
1089 fn iter_mut() {
1090 let mut obj_pool = ObjPool::new();
1091 let a = obj_pool.insert(10);
1092 let b = obj_pool.insert(20);
1093 let c = obj_pool.insert(30);
1094 let d = obj_pool.insert(40);
1095
1096 obj_pool.remove(b);
1097
1098 {
1099 let mut it = obj_pool.iter_mut();
1100 assert_eq!(it.next(), Some((a, &mut 10)));
1101 assert_eq!(it.next(), Some((c, &mut 30)));
1102 assert_eq!(it.next(), Some((d, &mut 40)));
1103 assert_eq!(it.next(), None);
1104 }
1105
1106 for (obj_id, value) in &mut obj_pool {
1107 *value += obj_id.get();
1108 }
1109
1110 let mut it = obj_pool.iter_mut();
1111 assert_eq!(*it.next().unwrap().1, 10 + a.get());
1112 assert_eq!(*it.next().unwrap().1, 30 + c.get());
1113 assert_eq!(*it.next().unwrap().1, 40 + d.get());
1114 assert_eq!(it.next(), None);
1115 }
1116
1117 #[test]
1118 fn from_iter() {
1119 let obj_pool: ObjPool<usize> = [10, 20, 30, 40].iter().cloned().collect();
1120
1121 let mut it = obj_pool.iter();
1122 assert_eq!(it.next(), Some((ObjPool::<usize>::index_to_obj_id(0), &10)));
1123 assert_eq!(it.next(), Some((ObjPool::<usize>::index_to_obj_id(1), &20)));
1124 assert_eq!(it.next(), Some((ObjPool::<usize>::index_to_obj_id(2), &30)));
1125 assert_eq!(it.next(), Some((ObjPool::<usize>::index_to_obj_id(3), &40)));
1126 assert_eq!(it.next(), None);
1127 }
1128}