slabigator/lib.rs
1#![doc = include_str!("../README.md")]
2#![warn(rustdoc::broken_intra_doc_links)]
3#![warn(missing_docs)]
4#![warn(clippy::pedantic)]
5#![allow(clippy::module_name_repetitions)]
6#![allow(clippy::missing_errors_doc)]
7#![allow(clippy::cast_possible_truncation)]
8
9//! # Slabigator
10//!
11//! A high-performance linked list with fixed capacity that doesn't perform dynamic memory
12//! allocations after initialization. It provides O(1) operations for adding, removing,
13//! and accessing elements.
14//!
15//! ## Overview
16//!
17//! Slabigator is designed for scenarios where memory allocation predictability is critical
18//! and you need stable references to elements. It allocates all memory upfront and provides
19//! slot numbers as stable references to elements.
20//!
21//! ## Key Features
22//!
23//! - Fixed capacity - no allocations during operations
24//! - O(1) push_front operation
25//! - O(1) pop_back operation
26//! - O(1) removal of any element by slot
27//! - Slots provide stable references to elements
28//! - Implements useful Rust traits like `FromIterator` and `Extend`
29//!
30//! ## Basic Usage
31//!
32//! ```rust
33//! use slabigator::Slab;
34//!
35//! // Create a slab with capacity for 3 elements
36//! let mut slab = Slab::with_capacity(3).unwrap();
37//!
38//! // Push elements to the front (returns slot numbers)
39//! let a = slab.push_front("a").unwrap();
40//! let b = slab.push_front("b").unwrap();
41//! let c = slab.push_front("c").unwrap();
42//!
43//! // Access by slot
44//! assert_eq!(slab.get(a).unwrap(), &"a");
45//! assert_eq!(slab.get(b).unwrap(), &"b");
46//! assert_eq!(slab.get(c).unwrap(), &"c");
47//!
48//! // Remove an element
49//! slab.remove(b).unwrap();
50//! assert_eq!(slab.len(), 2);
51//!
52//! // Iterate (order is from head to tail)
53//! let elements: Vec<_> = slab.iter().collect();
54//! assert_eq!(elements, vec![&"c", &"a"]);
55//!
56//! // Pop from the back (FIFO queue behavior)
57//! assert_eq!(slab.pop_back().unwrap(), "a");
58//! assert_eq!(slab.pop_back().unwrap(), "c");
59//! assert!(slab.is_empty());
60//! ```
61//!
62//! ## Advanced Features
63//!
64//! ### Default capacity
65//!
66//! ```rust
67//! use slabigator::Slab;
68//!
69//! // Creates a slab with default capacity (16)
70//! let slab: Slab<i32> = Slab::default();
71//! assert_eq!(slab.capacity(), 16);
72//! ```
73//!
74//! ### Creating from an iterator
75//!
76//! ```rust
77//! use slabigator::Slab;
78//!
79//! let values = vec![1, 2, 3, 4, 5];
80//! let slab: Slab<_> = values.iter().copied().collect();
81//!
82//! assert_eq!(slab.len(), 5);
83//! ```
84//!
85//! ### Extending a slab
86//!
87//! ```rust
88//! use slabigator::Slab;
89//!
90//! let mut slab = Slab::with_capacity(5).unwrap();
91//! slab.push_front(1).unwrap();
92//! slab.push_front(2).unwrap();
93//!
94//! // Extend with more elements
95//! slab.extend(vec![3, 4, 5]);
96//! assert_eq!(slab.len(), 5);
97//! ```
98
99use std::iter::Iterator;
100
101#[cfg(all(feature = "slot_u64", not(feature = "slot_usize")))]
102/// Slot type used for element references.
103/// This is u64 when the `slot_u64` feature is enabled.
104pub type Slot = u64;
105#[cfg(feature = "slot_usize")]
106/// Slot type used for element references.
107/// This is usize when the `slot_usize` feature is enabled.
108pub type Slot = usize;
109#[cfg(not(any(
110 all(feature = "slot_u64", not(feature = "slot_usize")),
111 feature = "slot_usize"
112)))]
113/// Slot type used for element references.
114/// This is u32 by default or when the `slot_u32` feature is enabled.
115pub type Slot = u32;
116
117const NUL: Slot = Slot::MAX;
118
119/// A fixed-capacity linked list that doesn't perform dynamic memory allocations after initialization.
120///
121/// # Overview
122///
123/// `Slab<D>` is a specialized data structure that allocates all of its memory upfront and provides
124/// stable slot numbers as references to elements. This makes it ideal for performance-critical
125/// applications where:
126///
127/// - Memory allocation patterns need to be predictable
128/// - You need stable references to elements
129/// - Fast O(1) operations are required
130/// - You know the maximum capacity in advance
131///
132/// # Core Operations
133///
134/// - **`push_front`**: Add elements to the head of the list in O(1) time
135/// - **`pop_back`**: Remove and return an element from the tail in O(1) time
136/// - **remove**: Delete any element by its slot number in O(1) time
137/// - **`get/get_mut`**: Access any element by its slot number in O(1) time
138///
139/// # Memory Behavior
140///
141/// The slab allocates all memory during creation with `with_capacity()`. No further allocations
142/// occur during subsequent operations. This provides predictable memory usage and avoids
143/// allocation-related performance issues.
144///
145/// # Implementation Details
146///
147/// Internally, the slab maintains:
148/// - A vector of elements
149/// - A linked list structure for tracking the order of elements
150/// - A free list for quick reuse of slots
151/// - A bitmap for validating slot access (when not using `releasefast` feature)
152///
153/// # Examples
154///
155/// ## Basic Operations
156///
157/// ```
158/// use slabigator::Slab;
159///
160/// // Create a new slab with capacity for 3 elements
161/// let mut slab = Slab::with_capacity(3).unwrap();
162///
163/// // Push elements to the front - each operation returns a slot number
164/// // The slot numbers are stable references that won't change
165/// // even when other elements are added or removed
166/// let slot_a = slab.push_front("a").unwrap();
167/// let slot_b = slab.push_front("b").unwrap();
168/// let slot_c = slab.push_front("c").unwrap();
169///
170/// // Slab is now full
171/// assert!(slab.is_full());
172/// assert_eq!(slab.len(), 3);
173///
174/// // Access elements by slot - these are direct lookups
175/// assert_eq!(slab.get(slot_a).unwrap(), &"a");
176/// assert_eq!(slab.get(slot_b).unwrap(), &"b");
177/// assert_eq!(slab.get(slot_c).unwrap(), &"c");
178///
179/// // Remove an element by slot
180/// slab.remove(slot_b).unwrap();
181/// assert_eq!(slab.len(), 2);
182/// #[cfg(not(feature = "releasefast"))]
183/// assert!(slab.get(slot_b).is_err()); // Slot b is no longer valid
184///
185/// // Pop elements from the back (FIFO order)
186/// let value = slab.pop_back().unwrap();
187/// assert_eq!(value, "a");
188/// assert_eq!(slab.len(), 1);
189///
190/// let value = slab.pop_back().unwrap();
191/// assert_eq!(value, "c");
192/// assert!(slab.is_empty());
193/// ```
194///
195/// ## Using as a FIFO Queue
196///
197/// ```
198/// use slabigator::Slab;
199///
200/// let mut queue = Slab::with_capacity(10).unwrap();
201///
202/// // Enqueue items (push to front)
203/// queue.push_front("first").unwrap();
204/// queue.push_front("second").unwrap();
205/// queue.push_front("third").unwrap();
206///
207/// // Dequeue items (pop from back) - FIFO order
208/// assert_eq!(queue.pop_back().unwrap(), "first");
209/// assert_eq!(queue.pop_back().unwrap(), "second");
210/// assert_eq!(queue.pop_back().unwrap(), "third");
211/// ```
212///
213/// ## Using for Object Pooling
214///
215/// ```
216/// use slabigator::Slab;
217///
218/// #[derive(Debug, PartialEq)]
219/// struct GameObject {
220/// id: u32,
221/// active: bool,
222/// }
223///
224/// // Create a pool of game objects
225/// let mut pool = Slab::with_capacity(100).unwrap();
226///
227/// // Create and add objects to the pool
228/// let slot1 = pool.push_front(GameObject { id: 1, active: true }).unwrap();
229/// let slot2 = pool.push_front(GameObject { id: 2, active: true }).unwrap();
230///
231/// // Deactivate an object (by mutating it)
232/// if let Ok(object) = pool.get_mut(slot1) {
233/// object.active = false;
234/// }
235///
236/// // Remove an object from the pool when no longer needed
237/// pool.remove(slot2).unwrap();
238/// ```
239#[derive(Debug)]
240pub struct Slab<D: Sized> {
241 vec_next: Vec<Slot>,
242 vec_prev: Vec<Slot>,
243 free_head: Slot,
244 head: Slot,
245 tail: Slot,
246 len: usize,
247 data: Vec<Option<D>>,
248 #[cfg(not(feature = "releasefast"))]
249 bitmap: Vec<u8>,
250}
251
252/// Error types that can occur during Slab operations.
253///
254/// The Slab API follows a design philosophy where operations that could fail return
255/// a `Result<T, Error>` rather than panicking. This allows error handling to be more
256/// explicit and gives the caller control over how to handle error conditions.
257///
258/// # Examples
259///
260/// ```
261/// use slabigator::{Slab, Error};
262///
263/// let mut slab = Slab::with_capacity(1).unwrap();
264/// slab.push_front("only element").unwrap();
265///
266/// // Attempt to add another element when slab is full
267/// match slab.push_front("one too many") {
268/// Ok(_) => println!("Element added successfully"),
269/// Err(Error::Full) => println!("Cannot add element: slab is full"),
270/// Err(_) => println!("Other error occurred"),
271/// }
272///
273/// // Attempt to access an invalid slot
274/// match slab.get(999) {
275/// Ok(_) => println!("Element retrieved"),
276/// Err(Error::InvalidSlot) => println!("Invalid slot"),
277/// Err(_) => println!("Other error occurred"),
278/// }
279/// ```
280#[derive(Debug, Clone, Hash, PartialEq, Eq)]
281pub enum Error {
282 /// Returned when the requested capacity during creation is too large for the
283 /// selected slot type. This occurs when the capacity would cause the slot index
284 /// to exceed the maximum value for the slot type (u32, u64, or usize).
285 TooLarge,
286
287 /// Returned when attempting to add an element to a slab that already contains
288 /// its maximum capacity of elements. Check `is_full()` before adding elements
289 /// or handle this error to implement graceful fallbacks.
290 Full,
291
292 /// Returned when:
293 /// - Accessing a slot that is out of bounds (>= capacity)
294 /// - Accessing a slot that doesn't contain an element (was never set or was removed)
295 /// - Attempting to remove an element from a slot that is invalid
296 ///
297 /// When not using the `releasefast` feature, all slot validity is checked.
298 InvalidSlot,
299
300 /// Returned when attempting to access or remove elements from an empty slab.
301 /// Check `is_empty()` before these operations or handle this error appropriately.
302 Empty,
303}
304
305impl std::error::Error for Error {}
306
307impl std::fmt::Display for Error {
308 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
309 match self {
310 Error::TooLarge => write!(f, "Capacity is too large for the slot type"),
311 Error::Full => write!(f, "Slab is full and cannot accept more elements"),
312 Error::InvalidSlot => write!(f, "Invalid slot or slot doesn't contain an element"),
313 Error::Empty => write!(f, "Slab is empty"),
314 }
315 }
316}
317
318impl<D: Sized> Slab<D> {
319 /// Creates a new slab with the given capacity.
320 ///
321 /// # Arguments
322 ///
323 /// * `capacity` - The maximum number of elements the slab can hold.
324 ///
325 /// # Returns
326 ///
327 /// * `Ok(Slab<D>)` - A new slab with the requested capacity.
328 /// * `Err(Error::TooLarge)` - If the capacity is too large for the slot type.
329 ///
330 /// # Examples
331 ///
332 /// ```
333 /// use slabigator::Slab;
334 ///
335 /// let slab = Slab::<String>::with_capacity(10).unwrap();
336 /// assert_eq!(slab.capacity(), 10);
337 /// assert_eq!(slab.len(), 0);
338 /// assert!(slab.is_empty());
339 /// ```
340 pub fn with_capacity(capacity: usize) -> Result<Self, Error> {
341 if capacity as Slot == NUL {
342 return Err(Error::TooLarge);
343 }
344 let mut vec_next = Vec::with_capacity(capacity);
345 for i in 0..(capacity - 1) {
346 vec_next.push(i as Slot + 1);
347 }
348 vec_next.push(NUL);
349
350 let mut vec_prev = Vec::with_capacity(capacity);
351 vec_prev.push(NUL);
352 for i in 1..capacity {
353 vec_prev.push(i as Slot - 1);
354 }
355
356 // Initialize data with None values instead of MaybeUninit
357 let mut data = Vec::with_capacity(capacity);
358 for _ in 0..capacity {
359 data.push(None);
360 }
361
362 #[cfg(not(feature = "releasefast"))]
363 let bitmap_size = (capacity + 7) / 8; // TODO: Replace with capacity.div_ceil(8) when stable
364
365 Ok(Self {
366 vec_next,
367 vec_prev,
368 free_head: 0,
369 head: NUL,
370 tail: NUL,
371 len: 0,
372 data,
373 #[cfg(not(feature = "releasefast"))]
374 bitmap: vec![0u8; bitmap_size],
375 })
376 }
377
378 /// Returns the capacity of the slab.
379 ///
380 /// # Examples
381 ///
382 /// ```
383 /// use slabigator::Slab;
384 ///
385 /// let slab = Slab::<i32>::with_capacity(10).unwrap();
386 /// assert_eq!(slab.capacity(), 10);
387 /// ```
388 #[inline]
389 #[must_use]
390 pub fn capacity(&self) -> usize {
391 self.data.capacity()
392 }
393
394 /// Returns the number of elements in the slab.
395 ///
396 /// # Examples
397 ///
398 /// ```
399 /// use slabigator::Slab;
400 ///
401 /// let mut slab = Slab::with_capacity(10).unwrap();
402 /// assert_eq!(slab.len(), 0);
403 ///
404 /// slab.push_front(42).unwrap();
405 /// assert_eq!(slab.len(), 1);
406 /// ```
407 #[inline]
408 #[must_use]
409 pub fn len(&self) -> usize {
410 self.len
411 }
412
413 /// Returns the number of elements that can still be stored.
414 ///
415 /// # Examples
416 ///
417 /// ```
418 /// use slabigator::Slab;
419 ///
420 /// let mut slab = Slab::with_capacity(3).unwrap();
421 /// assert_eq!(slab.free(), 3);
422 ///
423 /// slab.push_front(42).unwrap();
424 /// assert_eq!(slab.free(), 2);
425 /// ```
426 #[inline]
427 #[must_use]
428 pub fn free(&self) -> usize {
429 self.capacity() - self.len()
430 }
431
432 /// Returns `true` if the slab contains no elements.
433 ///
434 /// # Examples
435 ///
436 /// ```
437 /// use slabigator::Slab;
438 ///
439 /// let mut slab = Slab::with_capacity(10).unwrap();
440 /// assert!(slab.is_empty());
441 ///
442 /// slab.push_front(42).unwrap();
443 /// assert!(!slab.is_empty());
444 /// ```
445 #[inline]
446 #[must_use]
447 pub fn is_empty(&self) -> bool {
448 self.len() == 0
449 }
450
451 /// Returns `true` if the slab cannot hold any more elements.
452 ///
453 /// # Examples
454 ///
455 /// ```
456 /// use slabigator::Slab;
457 ///
458 /// let mut slab = Slab::with_capacity(2).unwrap();
459 /// assert!(!slab.is_full());
460 ///
461 /// slab.push_front(1).unwrap();
462 /// slab.push_front(2).unwrap();
463 /// assert!(slab.is_full());
464 /// ```
465 #[inline]
466 #[must_use]
467 pub fn is_full(&self) -> bool {
468 self.free_head == NUL
469 }
470
471 /// Returns a reference to an element given its slot number.
472 ///
473 /// # Arguments
474 ///
475 /// * `slot` - The slot number of the element to retrieve.
476 ///
477 /// # Returns
478 ///
479 /// * `Ok(&D)` - A reference to the element.
480 /// * `Err(Error::InvalidSlot)` - If the slot is invalid or doesn't contain an element.
481 ///
482 /// # Examples
483 ///
484 /// ```
485 /// use slabigator::Slab;
486 ///
487 /// let mut slab = Slab::with_capacity(10).unwrap();
488 /// let slot = slab.push_front("hello").unwrap();
489 ///
490 /// assert_eq!(slab.get(slot).unwrap(), &"hello");
491 /// ```
492 pub fn get(&self, slot: Slot) -> Result<&D, Error> {
493 let index = slot as usize;
494 if index >= self.capacity() {
495 return Err(Error::InvalidSlot);
496 }
497
498 #[cfg(not(feature = "releasefast"))]
499 {
500 if !self.bitmap_get(slot) {
501 return Err(Error::InvalidSlot);
502 }
503 }
504
505 // Use pattern matching to safely access the Option<D>
506 match &self.data[index] {
507 Some(value) => Ok(value),
508 None => Err(Error::InvalidSlot),
509 }
510 }
511
512 /// Returns a mutable reference to an element given its slot number.
513 ///
514 /// # Arguments
515 ///
516 /// * `slot` - The slot number of the element to retrieve.
517 ///
518 /// # Returns
519 ///
520 /// * `Ok(&mut D)` - A mutable reference to the element.
521 /// * `Err(Error::InvalidSlot)` - If the slot is invalid or doesn't contain an element.
522 ///
523 /// # Examples
524 ///
525 /// ```
526 /// use slabigator::Slab;
527 ///
528 /// let mut slab = Slab::with_capacity(10).unwrap();
529 /// let slot = slab.push_front("hello").unwrap();
530 ///
531 /// *slab.get_mut(slot).unwrap() = "world";
532 /// assert_eq!(slab.get(slot).unwrap(), &"world");
533 /// ```
534 pub fn get_mut(&mut self, slot: Slot) -> Result<&mut D, Error> {
535 let index = slot as usize;
536 if index >= self.capacity() {
537 return Err(Error::InvalidSlot);
538 }
539
540 #[cfg(not(feature = "releasefast"))]
541 {
542 if !self.bitmap_get(slot) {
543 return Err(Error::InvalidSlot);
544 }
545 }
546
547 // Use pattern matching to safely access the Option<D>
548 match &mut self.data[index] {
549 Some(value) => Ok(value),
550 None => Err(Error::InvalidSlot),
551 }
552 }
553
554 /// Prepends an element to the beginning of the slab.
555 ///
556 /// # Arguments
557 ///
558 /// * `value` - The value to prepend.
559 ///
560 /// # Returns
561 ///
562 /// * `Ok(Slot)` - The slot number of the newly added element.
563 /// * `Err(Error::Full)` - If the slab is full.
564 ///
565 /// # Examples
566 ///
567 /// ```
568 /// use slabigator::Slab;
569 ///
570 /// let mut slab = Slab::with_capacity(3).unwrap();
571 ///
572 /// let a = slab.push_front("a").unwrap();
573 /// let b = slab.push_front("b").unwrap();
574 /// let c = slab.push_front("c").unwrap();
575 ///
576 /// // Elements are in reverse order of insertion
577 /// let mut iter = slab.iter();
578 /// assert_eq!(iter.next(), Some(&"c"));
579 /// assert_eq!(iter.next(), Some(&"b"));
580 /// assert_eq!(iter.next(), Some(&"a"));
581 /// assert_eq!(iter.next(), None);
582 /// ```
583 pub fn push_front(&mut self, value: D) -> Result<Slot, Error> {
584 let free_slot = self.free_head;
585 if free_slot == NUL {
586 return Err(Error::Full);
587 }
588
589 let free_index = free_slot as usize;
590 let prev = self.vec_prev[free_index];
591 let next = self.vec_next[free_index];
592
593 if prev != NUL {
594 debug_assert_eq!(self.vec_next[prev as usize], free_slot);
595 self.vec_next[prev as usize] = next;
596 }
597
598 if next != NUL {
599 if !self.is_empty() {
600 debug_assert_eq!(self.vec_prev[next as usize], free_slot);
601 }
602 self.vec_prev[next as usize] = prev;
603 }
604
605 if self.head != NUL {
606 self.vec_prev[self.head as usize] = free_slot;
607 }
608
609 self.free_head = next;
610 self.vec_next[free_index] = self.head;
611 self.vec_prev[free_index] = NUL;
612
613 if self.head == NUL {
614 self.tail = free_slot;
615 }
616
617 self.head = free_slot;
618
619 // Store the value safely using Option
620 self.data[free_index] = Some(value);
621
622 self.len += 1;
623 debug_assert!(self.len <= self.capacity());
624
625 #[cfg(not(feature = "releasefast"))]
626 {
627 self.bitmap_set(free_slot);
628 }
629
630 Ok(free_slot)
631 }
632
633 /// Removes an element from the slab given its slot.
634 ///
635 /// # Arguments
636 ///
637 /// * `slot` - The slot number of the element to remove.
638 ///
639 /// # Returns
640 ///
641 /// * `Ok(())` - If the element was successfully removed.
642 /// * `Err(Error::InvalidSlot)` - If the slot is invalid or doesn't contain an element.
643 ///
644 /// # Examples
645 ///
646 /// ```
647 /// use slabigator::Slab;
648 ///
649 /// let mut slab = Slab::with_capacity(3).unwrap();
650 /// let a = slab.push_front("a").unwrap();
651 /// let b = slab.push_front("b").unwrap();
652 /// let c = slab.push_front("c").unwrap();
653 ///
654 /// assert_eq!(slab.len(), 3);
655 ///
656 /// slab.remove(b).unwrap();
657 /// assert_eq!(slab.len(), 2);
658 ///
659 /// // The element at slot `b` is no longer accessible
660 /// #[cfg(not(feature = "releasefast"))]
661 /// assert!(slab.get(b).is_err());
662 /// ```
663 pub fn remove(&mut self, slot: Slot) -> Result<(), Error> {
664 let index = slot as usize;
665 if index >= self.capacity() {
666 return Err(Error::InvalidSlot);
667 }
668
669 #[cfg(not(feature = "releasefast"))]
670 {
671 if !self.bitmap_get(slot) {
672 return Err(Error::InvalidSlot);
673 }
674 }
675
676 // Check if there's actually an element at this slot
677 if self.data[index].is_none() {
678 return Err(Error::InvalidSlot);
679 }
680
681 // Clear the data by replacing it with None
682 self.data[index] = None;
683
684 let prev = self.vec_prev[index];
685 let next = self.vec_next[index];
686
687 if prev != NUL {
688 debug_assert_eq!(self.vec_next[prev as usize], slot);
689 self.vec_next[prev as usize] = next;
690 }
691
692 if next != NUL {
693 if !self.is_empty() {
694 debug_assert_eq!(self.vec_prev[next as usize], slot);
695 }
696 self.vec_prev[next as usize] = prev;
697 }
698
699 if self.tail == slot {
700 self.tail = prev;
701 }
702
703 if self.head == slot {
704 self.head = next;
705 }
706
707 self.vec_prev[index] = NUL;
708 self.vec_next[index] = self.free_head;
709
710 if self.free_head != NUL {
711 self.vec_prev[self.free_head as usize] = slot;
712 }
713
714 self.free_head = slot;
715 debug_assert!(self.len > 0);
716 self.len -= 1;
717
718 #[cfg(not(feature = "releasefast"))]
719 {
720 self.bitmap_unset(slot);
721 }
722
723 Ok(())
724 }
725
726 /// Removes and returns the tail element of the slab.
727 ///
728 /// # Returns
729 ///
730 /// * `Some(D)` - The removed element.
731 /// * `None` - If the slab is empty.
732 ///
733 /// # Examples
734 ///
735 /// ```
736 /// use slabigator::Slab;
737 ///
738 /// let mut slab = Slab::with_capacity(3).unwrap();
739 /// slab.push_front("a").unwrap();
740 /// slab.push_front("b").unwrap();
741 /// slab.push_front("c").unwrap();
742 ///
743 /// assert_eq!(slab.pop_back(), Some("a"));
744 /// assert_eq!(slab.pop_back(), Some("b"));
745 /// assert_eq!(slab.pop_back(), Some("c"));
746 /// assert_eq!(slab.pop_back(), None);
747 /// ```
748 pub fn pop_back(&mut self) -> Option<D> {
749 let slot = self.tail;
750 if slot == NUL {
751 return None;
752 }
753
754 let index = slot as usize;
755
756 // Take the value out, replacing it with None
757 let value = self.data[index].take()?;
758
759 let prev = self.vec_prev[index];
760 debug_assert_eq!(self.vec_next[index], NUL);
761
762 if prev != NUL {
763 debug_assert_eq!(self.vec_next[prev as usize], slot);
764 self.vec_next[prev as usize] = NUL;
765 }
766
767 self.tail = prev;
768
769 if self.head == slot {
770 self.head = NUL;
771 }
772
773 self.vec_prev[index] = NUL;
774 self.vec_next[index] = self.free_head;
775
776 if self.free_head != NUL {
777 self.vec_prev[self.free_head as usize] = slot;
778 }
779
780 self.free_head = slot;
781 debug_assert!(self.len > 0);
782 self.len -= 1;
783
784 #[cfg(not(feature = "releasefast"))]
785 {
786 self.bitmap_unset(slot);
787 }
788
789 Some(value)
790 }
791
792 /// Returns an iterator over the elements of the slab.
793 ///
794 /// The iterator yields elements in order from head to tail.
795 ///
796 /// # Examples
797 ///
798 /// ```
799 /// use slabigator::Slab;
800 ///
801 /// let mut slab = Slab::with_capacity(3).unwrap();
802 /// slab.push_front("a").unwrap();
803 /// slab.push_front("b").unwrap();
804 /// slab.push_front("c").unwrap();
805 ///
806 /// let mut iter = slab.iter();
807 /// assert_eq!(iter.next(), Some(&"c"));
808 /// assert_eq!(iter.next(), Some(&"b"));
809 /// assert_eq!(iter.next(), Some(&"a"));
810 /// assert_eq!(iter.next(), None);
811 /// ```
812 #[must_use]
813 pub fn iter(&self) -> SlabIterator<D> {
814 SlabIterator {
815 list: self,
816 slot: None,
817 }
818 }
819
820 /// Checks if the slot contains an element.
821 ///
822 /// This method is only available when not using the `releasefast` feature.
823 ///
824 /// # Arguments
825 ///
826 /// * `slot` - The slot to check.
827 ///
828 /// # Returns
829 ///
830 /// * `true` - If the slot contains an element.
831 /// * `false` - If the slot is invalid or doesn't contain an element.
832 ///
833 /// # Examples
834 ///
835 /// ```
836 /// use slabigator::Slab;
837 ///
838 /// let mut slab = Slab::with_capacity(3).unwrap();
839 /// let slot = slab.push_front("hello").unwrap();
840 ///
841 /// assert!(slab.contains_slot(slot));
842 ///
843 /// slab.remove(slot).unwrap();
844 /// assert!(!slab.contains_slot(slot));
845 /// ```
846 #[cfg(not(feature = "releasefast"))]
847 #[must_use]
848 pub fn contains_slot(&self, slot: Slot) -> bool {
849 if (slot as usize) >= self.capacity() {
850 return false;
851 }
852 self.bitmap_get(slot)
853 }
854
855 #[cfg(not(feature = "releasefast"))]
856 #[inline]
857 fn bitmap_get(&self, slot: Slot) -> bool {
858 (self.bitmap[(slot as usize) / 8] & (1 << ((slot as usize) & 7))) != 0
859 }
860
861 #[cfg(not(feature = "releasefast"))]
862 #[inline]
863 fn bitmap_set(&mut self, slot: Slot) {
864 self.bitmap[(slot as usize) / 8] |= 1 << ((slot as usize) & 7);
865 }
866
867 #[cfg(not(feature = "releasefast"))]
868 #[inline]
869 fn bitmap_unset(&mut self, slot: Slot) {
870 self.bitmap[(slot as usize) / 8] &= !(1 << ((slot as usize) & 7));
871 }
872
873 /// Clears the slab, removing all elements.
874 ///
875 /// # Examples
876 ///
877 /// ```
878 /// use slabigator::Slab;
879 ///
880 /// let mut slab = Slab::with_capacity(3).unwrap();
881 /// slab.push_front("a").unwrap();
882 /// slab.push_front("b").unwrap();
883 ///
884 /// assert_eq!(slab.len(), 2);
885 /// slab.clear();
886 /// assert_eq!(slab.len(), 0);
887 /// assert!(slab.is_empty());
888 /// ```
889 pub fn clear(&mut self) {
890 // Drop all elements
891 let mut slot = self.head;
892 while slot != NUL {
893 let next = self.vec_next[slot as usize];
894 self.data[slot as usize] = None;
895
896 #[cfg(not(feature = "releasefast"))]
897 {
898 self.bitmap_unset(slot);
899 }
900
901 slot = next;
902 }
903
904 // Reset the slab state
905 let capacity = self.capacity();
906 for i in 0..(capacity - 1) {
907 self.vec_next[i] = (i + 1) as Slot;
908 }
909 self.vec_next[capacity - 1] = NUL;
910
911 self.vec_prev[0] = NUL;
912 for i in 1..capacity {
913 self.vec_prev[i] = (i - 1) as Slot;
914 }
915
916 self.free_head = 0;
917 self.head = NUL;
918 self.tail = NUL;
919 self.len = 0;
920 }
921}
922
923impl<D> Default for Slab<D> {
924 /// Creates a new empty slab with a default capacity.
925 ///
926 /// # Examples
927 ///
928 /// ```
929 /// use slabigator::Slab;
930 ///
931 /// let slab: Slab<i32> = Slab::default();
932 /// assert!(slab.is_empty());
933 /// assert_eq!(slab.capacity(), 16);
934 /// ```
935 fn default() -> Self {
936 Self::with_capacity(16).expect("Default capacity should always be valid")
937 }
938}
939
940impl<D> core::ops::Index<Slot> for Slab<D> {
941 type Output = D;
942
943 fn index(&self, slot: Slot) -> &Self::Output {
944 self.get(slot).expect("Invalid slot index")
945 }
946}
947
948impl<D> core::ops::IndexMut<Slot> for Slab<D> {
949 fn index_mut(&mut self, slot: Slot) -> &mut Self::Output {
950 self.get_mut(slot).expect("Invalid slot index")
951 }
952}
953
954/// An iterator over the elements of a slab.
955///
956/// This iterator yields elements from the slab in order from head to tail.
957#[derive(Debug)]
958pub struct SlabIterator<'a, D> {
959 list: &'a Slab<D>,
960 slot: Option<Slot>,
961}
962
963impl<'a, D> Iterator for SlabIterator<'a, D> {
964 type Item = &'a D;
965
966 fn next(&mut self) -> Option<Self::Item> {
967 let slot = self.slot.unwrap_or(self.list.head);
968 if slot == NUL {
969 return None;
970 }
971
972 let index = slot as usize;
973 let res = self.list.data[index].as_ref()?;
974
975 self.slot = Some(self.list.vec_next[index]);
976 Some(res)
977 }
978}
979
980impl<D> ExactSizeIterator for SlabIterator<'_, D> {
981 fn len(&self) -> usize {
982 self.list.len()
983 }
984}
985
986impl<'a, D> DoubleEndedIterator for SlabIterator<'a, D> {
987 fn next_back(&mut self) -> Option<&'a D> {
988 let slot = self.slot.unwrap_or(self.list.tail);
989 if slot == NUL {
990 return None;
991 }
992
993 let index = slot as usize;
994 let res = self.list.data[index].as_ref()?;
995
996 self.slot = Some(self.list.vec_prev[index]);
997 Some(res)
998 }
999}
1000
1001impl<'a, D> IntoIterator for &'a Slab<D> {
1002 type IntoIter = SlabIterator<'a, D>;
1003 type Item = &'a D;
1004
1005 fn into_iter(self) -> Self::IntoIter {
1006 self.iter()
1007 }
1008}
1009
1010impl<D: Clone> FromIterator<D> for Slab<D> {
1011 /// Creates a slab from an iterator.
1012 ///
1013 /// The slab will have a capacity equal to the number of elements in the iterator.
1014 /// Elements are inserted in reverse order, so that iterating the resulting slab
1015 /// will produce elements in the same order as the original iterator.
1016 ///
1017 /// # Examples
1018 ///
1019 /// ```
1020 /// use slabigator::Slab;
1021 ///
1022 /// let values = vec![1, 2, 3, 4, 5];
1023 /// let slab: Slab<_> = values.clone().into_iter().collect();
1024 ///
1025 /// // Verify size
1026 /// assert_eq!(slab.len(), 5);
1027 ///
1028 /// // Examine individual slots - elements are stored in reversed order
1029 /// // from the input sequence since push_front is used internally
1030 /// assert_eq!(*slab.get(0).unwrap(), 5);
1031 /// assert_eq!(*slab.get(1).unwrap(), 4);
1032 /// assert_eq!(*slab.get(2).unwrap(), 3);
1033 /// assert_eq!(*slab.get(3).unwrap(), 2);
1034 /// assert_eq!(*slab.get(4).unwrap(), 1);
1035 /// ```
1036 ///
1037 /// # Panics
1038 ///
1039 /// Panics if the iterator contains too many elements for the slot type.
1040 fn from_iter<I: IntoIterator<Item = D>>(iter: I) -> Self {
1041 let iter = iter.into_iter();
1042 let (min, max_size) = iter.size_hint();
1043
1044 // Use max_size if available, otherwise min
1045 let capacity = max_size.unwrap_or(min);
1046
1047 // Try to create a slab with the estimated capacity
1048 let mut slab = Self::with_capacity(capacity).expect("Iterator too large for slab capacity");
1049
1050 // Insert elements in reverse order (so iterating matches original order)
1051 let mut vec: Vec<D> = iter.collect();
1052 while let Some(item) = vec.pop() {
1053 if slab.push_front(item.clone()).is_err() {
1054 // If we get here, our size hint was wrong - try to recover by
1055 // creating a larger slab and moving elements
1056 let new_capacity = slab.capacity() * 2;
1057 let mut new_slab = Self::with_capacity(new_capacity)
1058 .expect("Iterator too large for slab capacity");
1059
1060 // Move elements from old slab to new one
1061 while let Some(old_item) = slab.pop_back() {
1062 new_slab
1063 .push_front(old_item)
1064 .expect("New slab should have enough capacity");
1065 }
1066
1067 // Add the current item
1068 new_slab
1069 .push_front(item)
1070 .expect("New slab should have enough capacity");
1071
1072 // Replace with the new slab
1073 slab = new_slab;
1074 }
1075 }
1076
1077 slab
1078 }
1079}
1080
1081impl<D: Clone> Extend<D> for Slab<D> {
1082 /// Extends the slab with the elements from an iterator.
1083 ///
1084 /// # Examples
1085 ///
1086 /// ```
1087 /// use slabigator::Slab;
1088 ///
1089 /// let mut slab = Slab::with_capacity(10).unwrap();
1090 /// slab.push_front(1).unwrap();
1091 /// slab.push_front(2).unwrap();
1092 ///
1093 /// slab.extend(vec![3, 4, 5]);
1094 /// assert_eq!(slab.len(), 5);
1095 ///
1096 /// // The slot assignment is not sequential but depends on the internal free list.
1097 /// // We can verify the order by iterating instead.
1098 /// let items: Vec<_> = slab.iter().copied().collect();
1099 /// assert_eq!(items, vec![5, 4, 3, 2, 1]);
1100 /// ```
1101 ///
1102 /// # Panics
1103 ///
1104 /// Panics if the slab doesn't have enough capacity for all elements in the iterator.
1105 fn extend<I: IntoIterator<Item = D>>(&mut self, iter: I) {
1106 for item in iter {
1107 self.push_front(item).expect("Slab full during extend");
1108 }
1109 }
1110}
1111
1112// Test implementations
1113#[test]
1114fn test() {
1115 let mut slab = Slab::with_capacity(3).unwrap();
1116 let a = slab.push_front(Box::new(1)).unwrap();
1117 let b = slab.push_front(Box::new(2)).unwrap();
1118 slab.push_front(Box::new(3)).unwrap();
1119 assert_eq!(slab.len(), 3);
1120 assert!(slab.push_front(Box::new(4)).is_err());
1121 slab.remove(a).unwrap();
1122 slab.remove(b).unwrap();
1123 assert_eq!(slab.len(), 1);
1124 let cv = slab.pop_back().unwrap();
1125 assert_eq!(*cv, 3);
1126}
1127
1128#[test]
1129fn test2() {
1130 use std::collections::VecDeque;
1131
1132 use rand::prelude::*;
1133
1134 let mut rng = rand::rng();
1135 let capacity = rng.random_range(1..=50);
1136 let mut slab = Slab::with_capacity(capacity).unwrap();
1137
1138 let mut c: u64 = 0;
1139 let mut expected_len: usize = 0;
1140 let mut deque = VecDeque::with_capacity(capacity);
1141 for _ in 0..1_000_000 {
1142 let x = rng.random_range(0..=3);
1143 match x {
1144 0 => match slab.push_front(c) {
1145 Err(_) => {
1146 assert!(slab.is_full());
1147 assert_eq!(slab.free(), 0);
1148 }
1149 Ok(idx) => {
1150 deque.push_front(idx);
1151 expected_len += 1;
1152 assert!(expected_len <= capacity);
1153 assert_eq!(slab.free(), capacity - expected_len);
1154 }
1155 },
1156 1 => match slab.pop_back() {
1157 None => {
1158 assert!(slab.is_empty());
1159 assert_eq!(slab.free(), capacity);
1160 }
1161 Some(_x) => {
1162 deque.pop_back().unwrap();
1163 expected_len -= 1;
1164 assert_eq!(slab.free(), capacity - expected_len);
1165 if expected_len == 0 {
1166 assert!(slab.is_empty());
1167 }
1168 }
1169 },
1170 2 => {
1171 if slab.is_empty() {
1172 continue;
1173 }
1174 let deque_len = deque.len();
1175 if deque_len == 0 {
1176 continue;
1177 }
1178 let r = rng.random_range(0..deque_len);
1179 let idx = deque.remove(r).unwrap();
1180 slab.remove(idx).unwrap();
1181 expected_len -= 1;
1182 assert_eq!(slab.free(), capacity - expected_len);
1183 }
1184 3 => {
1185 // Only test slots that we know are valid in the deque
1186 if deque.is_empty() {
1187 continue;
1188 }
1189 let r = rng.random_range(0..deque.len());
1190 let slot = deque[r];
1191
1192 // Remove from the deque first
1193 let idx = deque.iter().position(|&x| x == slot).unwrap();
1194 deque.remove(idx);
1195
1196 // Then remove from the slab
1197 slab.remove(slot).unwrap();
1198 expected_len -= 1;
1199 assert_eq!(slab.free(), capacity - expected_len);
1200 }
1201 _ => unreachable!(),
1202 }
1203 assert_eq!(slab.len(), expected_len);
1204 c += 1;
1205 }
1206}
1207
1208#[test]
1209fn test_default() {
1210 let slab: Slab<i32> = Slab::default();
1211 assert_eq!(slab.capacity(), 16);
1212 assert_eq!(slab.len(), 0);
1213 assert!(slab.is_empty());
1214}
1215
1216#[test]
1217fn test_from_iterator() {
1218 // Create a vector of test values
1219 let values = vec![1, 2, 3, 4, 5];
1220
1221 // Create a slab from the vector
1222 let slab: Slab<i32> = values.clone().into_iter().collect();
1223
1224 // Verify the length
1225 assert_eq!(slab.len(), 5);
1226
1227 // Test the behavior more directly by comparing specific indices
1228
1229 // The FromIterator implementation uses push_front, which should reverse the order
1230 // Manual verification of the data through slots
1231 if slab.len() == 5 {
1232 assert_eq!(*slab.get(0).unwrap(), 5); // Last element in input, first in slab
1233 assert_eq!(*slab.get(1).unwrap(), 4);
1234 assert_eq!(*slab.get(2).unwrap(), 3);
1235 assert_eq!(*slab.get(3).unwrap(), 2);
1236 assert_eq!(*slab.get(4).unwrap(), 1); // First element in input, last in slab
1237 }
1238}
1239
1240#[test]
1241fn test_extend() {
1242 let mut slab = Slab::with_capacity(5).unwrap();
1243 slab.push_front(1).unwrap();
1244 slab.push_front(2).unwrap();
1245
1246 slab.extend(vec![3, 4, 5]);
1247 assert_eq!(slab.len(), 5);
1248
1249 // Collect the items to see what's actually there
1250 let items: Vec<_> = slab.iter().copied().collect();
1251
1252 // Elements appear in the reverse order of how they were added
1253 // push_front(1), push_front(2), then extend with [3,4,5]
1254 // The extend implementation uses push_front for each element
1255 assert_eq!(items, vec![5, 4, 3, 2, 1]);
1256}
1257
1258#[test]
1259fn test_clear() {
1260 let mut slab = Slab::with_capacity(3).unwrap();
1261 slab.push_front(1).unwrap();
1262 slab.push_front(2).unwrap();
1263 slab.push_front(3).unwrap();
1264
1265 assert_eq!(slab.len(), 3);
1266 assert!(slab.is_full());
1267
1268 slab.clear();
1269
1270 assert_eq!(slab.len(), 0);
1271 assert!(slab.is_empty());
1272 assert!(!slab.is_full());
1273
1274 // Should be able to add elements again
1275 let a = slab.push_front(4).unwrap();
1276 let b = slab.push_front(5).unwrap();
1277 let c = slab.push_front(6).unwrap();
1278
1279 assert_eq!(slab.len(), 3);
1280 assert!(slab.is_full());
1281
1282 // We can get elements by slot
1283 assert_eq!(*slab.get(a).unwrap(), 4);
1284 assert_eq!(*slab.get(b).unwrap(), 5);
1285 assert_eq!(*slab.get(c).unwrap(), 6);
1286}