iceoryx2_bb_container/
slotmap.rs

1// Copyright (c) 2024 Contributors to the Eclipse Foundation
2//
3// See the NOTICE file(s) distributed with this work for additional
4// information regarding copyright ownership.
5//
6// This program and the accompanying materials are made available under the
7// terms of the Apache Software License 2.0 which is available at
8// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
9// which is available at https://opensource.org/licenses/MIT.
10//
11// SPDX-License-Identifier: Apache-2.0 OR MIT
12
13//! A SlotMap is a container that has a static unique key for every stored value. Adding or
14//! removing values to the SlotMap do not change the unique key of the remaining values.
15//! Multiple variationes of that container are available.
16//!
17//!  * [`SlotMap`](crate::slotmap::SlotMap), run-time fixed-size slotmap that is not shared-memory
18//!    compatible since the memory resides in the heap.
19//!  * [`FixedSizeSlotMap`](crate::slotmap::FixedSizeSlotMap), compile-time fixed-size slotmap that
20//!    is self-contained and shared-memory compatible.
21//!  * [`RelocatableSlotMap`](crate::slotmap::RelocatableSlotMap), run-time fixed-size slotmap that
22//!    is shared-memory compatible.
23//!
24//! The SlotMap shall satisfy the following requirements:
25//!
26//!  * A new element can be inserted with a max runtime of `O(1)`
27//!  * A new element can be inserted at a user-provided key with a max runtime of `O(1)`
28//!  * An element can be removed by providing the corresponding key with a max runtime of `O(1)`
29//!  * One can iterate over all elements of the SlotMap.
30//!
31//! The SlotMap is the perfect container when elements shall be added, removed and accesses quickly
32//! but iteration is allowed to be slow.
33//!
34//! # User Examples
35//!
36//! ```
37//! # extern crate iceoryx2_loggers;
38//!
39//! use iceoryx2_bb_container::slotmap::FixedSizeSlotMap;
40//!
41//! const CAPACITY: usize = 123;
42//! let mut slotmap = FixedSizeSlotMap::<u64, CAPACITY>::new();
43//!
44//! let key = slotmap.insert(78181).unwrap();
45//!
46//! println!("value: {:?}", slotmap.get(key));
47//! ```
48
49use crate::queue::MetaQueue;
50use crate::vec::MetaVec;
51use crate::{queue::RelocatableQueue, vec::RelocatableVec};
52use core::mem::MaybeUninit;
53use iceoryx2_bb_concurrency::atomic::AtomicBool;
54use iceoryx2_bb_derive_macros::ZeroCopySend;
55use iceoryx2_bb_elementary::bump_allocator::BumpAllocator;
56use iceoryx2_bb_elementary::relocatable_ptr::GenericRelocatablePointer;
57use iceoryx2_bb_elementary_traits::generic_pointer::GenericPointer;
58use iceoryx2_bb_elementary_traits::owning_pointer::GenericOwningPointer;
59use iceoryx2_bb_elementary_traits::placement_default::PlacementDefault;
60pub use iceoryx2_bb_elementary_traits::relocatable_container::RelocatableContainer;
61use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
62use iceoryx2_log::{fail, fatal_panic};
63
64/// A key of a [`SlotMap`], [`RelocatableSlotMap`] or [`FixedSizeSlotMap`] that identifies a
65/// value.
66#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
67pub struct SlotMapKey(usize);
68
69impl SlotMapKey {
70    /// Creates a new [`SlotMapKey`] with the specified value.
71    pub fn new(value: usize) -> Self {
72        Self(value)
73    }
74
75    /// Returns the underlying value of the [`SlotMapKey`].
76    pub fn value(&self) -> usize {
77        self.0
78    }
79}
80
81#[repr(C)]
82#[derive(Debug, Clone, Copy, ZeroCopySend)]
83pub(crate) struct FreeListEntry {
84    previous: usize,
85    next: usize,
86}
87
88/// A runtime fixed-size, non-shared memory compatible [`SlotMap`]. The [`SlotMap`]s memory resides
89/// in the heap.
90pub type SlotMap<T> = MetaSlotMap<T, GenericOwningPointer>;
91
92/// A runtime fixed-size, shared-memory compatible [`RelocatableSlotMap`].
93pub type RelocatableSlotMap<T> = MetaSlotMap<T, GenericRelocatablePointer>;
94
95const INVALID: usize = usize::MAX;
96
97#[doc(hidden)]
98/// The iterator of a [`SlotMap`], [`RelocatableSlotMap`] or [`FixedSizeSlotMap`].
99pub struct Iter<'slotmap, T, Ptr: GenericPointer> {
100    slotmap: &'slotmap MetaSlotMap<T, Ptr>,
101    key: SlotMapKey,
102}
103
104#[doc(hidden)]
105pub type OwningIter<'slotmap, T> = Iter<'slotmap, T, GenericOwningPointer>;
106#[doc(hidden)]
107pub type RelocatableIter<'slotmap, T> = Iter<'slotmap, T, GenericRelocatablePointer>;
108
109impl<'slotmap, T, Ptr: GenericPointer> Iterator for Iter<'slotmap, T, Ptr> {
110    type Item = (SlotMapKey, &'slotmap T);
111
112    fn next(&mut self) -> Option<Self::Item> {
113        if let Some((next_key, value)) = self.slotmap.next_available_key_after(self.key) {
114            self.key.0 = next_key.0 + 1;
115            Some((next_key, value))
116        } else {
117            None
118        }
119    }
120}
121
122#[doc(hidden)]
123#[repr(C)]
124#[derive(Debug)]
125pub struct MetaSlotMap<T, Ptr: GenericPointer> {
126    idx_to_data: MetaVec<usize, Ptr>,
127    idx_to_data_free_list: MetaVec<FreeListEntry, Ptr>,
128    data: MetaVec<Option<T>, Ptr>,
129    data_next_free_index: MetaQueue<usize, Ptr>,
130    idx_to_data_free_list_head: usize,
131    is_initialized: AtomicBool,
132    len: usize,
133}
134
135impl<T, Ptr: GenericPointer> MetaSlotMap<T, Ptr> {
136    #[inline(always)]
137    fn verify_init(&self, source: &str) {
138        debug_assert!(
139                self.is_initialized
140                    .load(core::sync::atomic::Ordering::Relaxed),
141                "From: MetaSlotMap<{}>::{}, Undefined behavior - the object was not initialized with 'init' before.",
142                core::any::type_name::<T>(), source
143            );
144    }
145
146    fn next_available_key_after(&self, start: SlotMapKey) -> Option<(SlotMapKey, &T)> {
147        let idx_to_data = &self.idx_to_data;
148
149        for n in start.0..idx_to_data.len() {
150            let data_idx = self.idx_to_data[n];
151            if data_idx != INVALID {
152                return Some((
153                    SlotMapKey(n),
154                    self.data[data_idx].as_ref().expect(
155                        "By contract, data contains a value when idx_to_data contains a value",
156                    ),
157                ));
158            }
159        }
160
161        None
162    }
163
164    pub(crate) unsafe fn initialize_data_structures(&mut self) {
165        let capacity = self.capacity_impl();
166        for n in 0..capacity {
167            self.idx_to_data.push_impl(INVALID);
168            self.data.push_impl(None);
169            self.data_next_free_index.push_impl(n);
170
171            let previous = if n == 0 { INVALID } else { n - 1 };
172            let next = if n < capacity - 1 { n + 1 } else { INVALID };
173            self.idx_to_data_free_list
174                .push_impl(FreeListEntry { previous, next });
175        }
176    }
177
178    pub(crate) unsafe fn iter_impl(&self) -> Iter<'_, T, Ptr> {
179        self.verify_init("iter()");
180        Iter {
181            slotmap: self,
182            key: SlotMapKey(0),
183        }
184    }
185
186    pub(crate) unsafe fn contains_impl(&self, key: SlotMapKey) -> bool {
187        self.verify_init("contains()");
188        self.idx_to_data[key.0] != INVALID
189    }
190
191    pub(crate) unsafe fn get_impl(&self, key: SlotMapKey) -> Option<&T> {
192        self.verify_init("get()");
193        match self.idx_to_data[key.0] {
194            INVALID => None,
195            n => Some(self.data[n].as_ref().expect(
196                "data and idx_to_data correspond and this value must be always available.",
197            )),
198        }
199    }
200
201    pub(crate) unsafe fn get_mut_impl(&mut self, key: SlotMapKey) -> Option<&mut T> {
202        self.verify_init("get_mut()");
203        match self.idx_to_data[key.0] {
204            INVALID => None,
205            n => Some(self.data[n].as_mut().expect(
206                "data and idx_to_data correspond and this value must be always available.",
207            )),
208        }
209    }
210
211    unsafe fn acquire_next_free_index(&mut self) -> Option<usize> {
212        if self.idx_to_data_free_list_head == INVALID {
213            return None;
214        }
215
216        let free_idx = self.idx_to_data_free_list_head;
217        let next = self.idx_to_data_free_list[free_idx].next;
218
219        if next != INVALID {
220            self.idx_to_data_free_list[next].previous = INVALID;
221        }
222        self.idx_to_data_free_list_head = next;
223        Some(free_idx)
224    }
225
226    unsafe fn claim_index(&mut self, idx: usize) {
227        if idx >= self.capacity_impl() {
228            return;
229        }
230
231        let entry = self.idx_to_data_free_list[idx];
232        if entry.previous != INVALID {
233            self.idx_to_data_free_list[entry.previous].next = entry.next;
234        }
235        if entry.next != INVALID {
236            self.idx_to_data_free_list[entry.next].previous = entry.previous;
237        }
238        self.idx_to_data_free_list[idx].next = INVALID;
239        self.idx_to_data_free_list[idx].previous = INVALID;
240    }
241
242    unsafe fn release_free_index(&mut self, idx: usize) {
243        if self.idx_to_data_free_list_head != INVALID {
244            self.idx_to_data_free_list[self.idx_to_data_free_list_head].previous = idx;
245        }
246
247        self.idx_to_data_free_list[idx] = FreeListEntry {
248            previous: INVALID,
249            next: self.idx_to_data_free_list_head,
250        };
251
252        self.idx_to_data_free_list_head = idx;
253    }
254
255    pub(crate) unsafe fn insert_impl(&mut self, value: T) -> Option<SlotMapKey> {
256        self.verify_init("insert()");
257        self.acquire_next_free_index().map(|key| {
258            let key = SlotMapKey(key);
259            self.store_value(key, value);
260            key
261        })
262    }
263
264    pub(crate) unsafe fn insert_at_impl(&mut self, key: SlotMapKey, value: T) -> bool {
265        self.verify_init("insert_at()");
266        self.claim_index(key.value());
267        self.store_value(key, value)
268    }
269
270    pub(crate) unsafe fn store_value(&mut self, key: SlotMapKey, value: T) -> bool {
271        self.verify_init("store()");
272        if key.0 > self.capacity_impl() {
273            return false;
274        }
275
276        let data_idx = self.idx_to_data[key.0];
277        if data_idx != INVALID {
278            self.data[data_idx] = Some(value);
279        } else {
280            let n = self.data_next_free_index.pop_impl().expect(
281                "data and idx_to_data correspond and there must be always a free index available.",
282            );
283            self.idx_to_data[key.0] = n;
284            self.data[n] = Some(value);
285            self.len += 1;
286        }
287
288        true
289    }
290
291    pub(crate) unsafe fn remove_impl(&mut self, key: SlotMapKey) -> Option<T> {
292        self.verify_init("remove()");
293        if key.0 > self.idx_to_data.len() {
294            return None;
295        }
296
297        let data_idx = self.idx_to_data[key.0];
298        if data_idx != INVALID {
299            let ret = self.data[data_idx].take();
300            let push_result = self.data_next_free_index.push_impl(data_idx);
301            debug_assert!(push_result);
302            self.release_free_index(key.0);
303            self.idx_to_data[key.0] = INVALID;
304            self.len -= 1;
305            ret
306        } else {
307            None
308        }
309    }
310
311    pub(crate) unsafe fn next_free_key_impl(&self) -> Option<SlotMapKey> {
312        self.verify_init("next_free_key()");
313        if self.idx_to_data_free_list_head == INVALID {
314            return None;
315        }
316
317        Some(SlotMapKey::new(self.idx_to_data_free_list_head))
318    }
319
320    pub(crate) fn len_impl(&self) -> usize {
321        self.len
322    }
323
324    pub(crate) fn capacity_impl(&self) -> usize {
325        self.idx_to_data.capacity()
326    }
327
328    pub(crate) fn is_empty_impl(&self) -> bool {
329        self.len_impl() == 0
330    }
331
332    pub(crate) fn is_full_impl(&self) -> bool {
333        self.len_impl() == self.capacity_impl()
334    }
335}
336
337impl<T> RelocatableContainer for RelocatableSlotMap<T> {
338    unsafe fn new_uninit(capacity: usize) -> Self {
339        Self {
340            len: 0,
341            idx_to_data_free_list_head: 0,
342            idx_to_data: RelocatableVec::new_uninit(capacity),
343            idx_to_data_free_list: RelocatableVec::new_uninit(capacity),
344            data: RelocatableVec::new_uninit(capacity),
345            data_next_free_index: RelocatableQueue::new_uninit(capacity),
346            is_initialized: AtomicBool::new(false),
347        }
348    }
349
350    unsafe fn init<Allocator: iceoryx2_bb_elementary_traits::allocator::BaseAllocator>(
351        &mut self,
352        allocator: &Allocator,
353    ) -> Result<(), iceoryx2_bb_elementary_traits::allocator::AllocationError> {
354        if self
355            .is_initialized
356            .load(core::sync::atomic::Ordering::Relaxed)
357        {
358            fatal_panic!(from "RelocatableSlotMap::init()", "Memory already initialized. Initializing it twice may lead to undefined behavior.");
359        }
360        let msg = "Unable to initialize RelocatableSlotMap";
361        fail!(from "RelocatableSlotMap::init()",
362                  when self.idx_to_data.init(allocator),
363                  "{msg} since the underlying idx_to_data vector could not be initialized.");
364        fail!(from "RelocatableSlotMap::init()",
365                  when self.idx_to_data_free_list.init(allocator),
366                  "{msg} since the underlying idx_to_data_free_list vec could not be initialized.");
367        fail!(from "RelocatableSlotMap::init()",
368                  when self.data.init(allocator),
369                  "{msg} since the underlying data vector could not be initialized.");
370        fail!(from "RelocatableSlotMap::init()",
371                  when self.data_next_free_index.init(allocator),
372                  "{msg} since the underlying data_next_free_index queue could not be initialized.");
373
374        self.initialize_data_structures();
375        self.is_initialized
376            .store(true, core::sync::atomic::Ordering::Relaxed);
377        Ok(())
378    }
379
380    fn memory_size(capacity: usize) -> usize {
381        Self::const_memory_size(capacity)
382    }
383}
384
385impl<T> SlotMap<T> {
386    /// Creates a new runtime-fixed size [`SlotMap`] on the heap with the given capacity.
387    pub fn new(capacity: usize) -> Self {
388        let mut new_self = Self {
389            len: 0,
390            idx_to_data_free_list_head: 0,
391            idx_to_data: MetaVec::new(capacity),
392            idx_to_data_free_list: MetaVec::new(capacity),
393            data: MetaVec::new(capacity),
394            data_next_free_index: MetaQueue::new(capacity),
395            is_initialized: AtomicBool::new(true),
396        };
397        unsafe { new_self.initialize_data_structures() };
398        new_self
399    }
400
401    /// Returns the [`Iter`]ator to iterate over all entries.
402    pub fn iter(&self) -> OwningIter<'_, T> {
403        unsafe { self.iter_impl() }
404    }
405
406    /// Returns `true` if the provided `key` is contained, otherwise `false`.
407    pub fn contains(&self, key: SlotMapKey) -> bool {
408        unsafe { self.contains_impl(key) }
409    }
410
411    /// Returns a reference to the value stored under the given key. If there is no such key,
412    /// [`None`] is returned.
413    pub fn get(&self, key: SlotMapKey) -> Option<&T> {
414        unsafe { self.get_impl(key) }
415    }
416
417    /// Returns a mutable reference to the value stored under the given key. If there is no
418    /// such key, [`None`] is returned.
419    pub fn get_mut(&mut self, key: SlotMapKey) -> Option<&mut T> {
420        unsafe { self.get_mut_impl(key) }
421    }
422
423    /// Insert a value and returns the corresponding [`SlotMapKey`]. If the container is full
424    /// [`None`] is returned.
425    pub fn insert(&mut self, value: T) -> Option<SlotMapKey> {
426        unsafe { self.insert_impl(value) }
427    }
428
429    /// Insert a value at the specified [`SlotMapKey`] and returns true.  If the provided key
430    /// is out-of-bounds it returns `false` and adds nothing. If there is already a value
431    /// stored at the `key`s index, the value is overridden with the provided value.
432    pub fn insert_at(&mut self, key: SlotMapKey, value: T) -> bool {
433        unsafe { self.insert_at_impl(key, value) }
434    }
435
436    /// Removes a value at the specified [`SlotMapKey`]. If there was no value corresponding
437    /// to the [`SlotMapKey`] it returns None, otherwise Some(value).
438    pub fn remove(&mut self, key: SlotMapKey) -> Option<T> {
439        unsafe { self.remove_impl(key) }
440    }
441
442    /// Returns the [`SlotMapKey`] that will be used when the user calls
443    /// [`SlotMap::insert()`]. If the [`SlotMap`] is full it returns [`None`].
444    pub fn next_free_key(&self) -> Option<SlotMapKey> {
445        unsafe { self.next_free_key_impl() }
446    }
447
448    /// Returns the number of stored values.
449    pub fn len(&self) -> usize {
450        self.len_impl()
451    }
452
453    /// Returns the capacity.
454    pub fn capacity(&self) -> usize {
455        self.capacity_impl()
456    }
457
458    /// Returns true if the container is empty, otherwise false.
459    pub fn is_empty(&self) -> bool {
460        self.is_empty_impl()
461    }
462
463    /// Returns true if the container is full, otherwise false.
464    pub fn is_full(&self) -> bool {
465        self.is_full_impl()
466    }
467}
468
469unsafe impl<T: ZeroCopySend> ZeroCopySend for RelocatableSlotMap<T> {}
470
471impl<T> RelocatableSlotMap<T> {
472    /// Returns how many memory the [`RelocatableSlotMap`] will allocate from the allocator
473    /// in [`RelocatableSlotMap::init()`].
474    pub const fn const_memory_size(capacity: usize) -> usize {
475        RelocatableVec::<usize>::const_memory_size(capacity)
476            + RelocatableVec::<FreeListEntry>::const_memory_size(capacity)
477            + RelocatableVec::<Option<T>>::const_memory_size(capacity)
478            + RelocatableQueue::<usize>::const_memory_size(capacity)
479    }
480
481    /// Returns the [`Iter`]ator to iterate over all entries.
482    ///
483    /// # Safety
484    ///
485    ///  * [`RelocatableSlotMap::init()`] must be called once before
486    ///
487    pub unsafe fn iter(&self) -> RelocatableIter<'_, T> {
488        self.iter_impl()
489    }
490
491    /// Returns `true` if the provided `key` is contained, otherwise `false`.
492    ///
493    /// # Safety
494    ///
495    ///  * [`RelocatableSlotMap::init()`] must be called once before
496    ///
497    pub unsafe fn contains(&self, key: SlotMapKey) -> bool {
498        self.contains_impl(key)
499    }
500
501    /// Returns a reference to the value stored under the given key. If there is no such key,
502    /// [`None`] is returned.
503    ///
504    /// # Safety
505    ///
506    ///  * [`RelocatableSlotMap::init()`] must be called once before
507    ///
508    pub unsafe fn get(&self, key: SlotMapKey) -> Option<&T> {
509        self.get_impl(key)
510    }
511
512    /// Returns a mutable reference to the value stored under the given key. If there is no
513    /// such key, [`None`] is returned.
514    ///
515    /// # Safety
516    ///
517    ///  * [`RelocatableSlotMap::init()`] must be called once before
518    ///
519    pub unsafe fn get_mut(&mut self, key: SlotMapKey) -> Option<&mut T> {
520        self.get_mut_impl(key)
521    }
522
523    /// Insert a value and returns the corresponding [`SlotMapKey`]. If the container is full
524    /// [`None`] is returned.
525    ///
526    /// # Safety
527    ///
528    ///  * [`RelocatableSlotMap::init()`] must be called once before
529    ///
530    pub unsafe fn insert(&mut self, value: T) -> Option<SlotMapKey> {
531        self.insert_impl(value)
532    }
533
534    /// Insert a value at the specified [`SlotMapKey`] and returns true.  If the provided key
535    /// is out-of-bounds it returns `false` and adds nothing. If there is already a value
536    /// stored at the `key`s index, the value is overridden with the provided value.
537    ///
538    /// # Safety
539    ///
540    ///  * [`RelocatableSlotMap::init()`] must be called once before
541    ///
542    pub unsafe fn insert_at(&mut self, key: SlotMapKey, value: T) -> bool {
543        self.insert_at_impl(key, value)
544    }
545
546    /// Removes a value at the specified [`SlotMapKey`]. If there was no value corresponding
547    /// to the [`SlotMapKey`] it returns None, otherwise Some(value).
548    ///
549    /// # Safety
550    ///
551    ///  * [`RelocatableSlotMap::init()`] must be called once before
552    ///
553    pub unsafe fn remove(&mut self, key: SlotMapKey) -> Option<T> {
554        self.remove_impl(key)
555    }
556
557    /// Returns the [`SlotMapKey`] that will be used when the user calls
558    /// [`SlotMap::insert()`]. If the [`SlotMap`] is full it returns [`None`].
559    ///
560    /// # Safety
561    ///
562    ///  * [`RelocatableSlotMap::init()`] must be called once before
563    ///
564    pub unsafe fn next_free_key(&self) -> Option<SlotMapKey> {
565        self.next_free_key_impl()
566    }
567
568    /// Returns the number of stored values.
569    pub fn len(&self) -> usize {
570        self.len_impl()
571    }
572
573    /// Returns the capacity.
574    pub fn capacity(&self) -> usize {
575        self.capacity_impl()
576    }
577
578    /// Returns true if the container is empty, otherwise false.
579    pub fn is_empty(&self) -> bool {
580        self.is_empty_impl()
581    }
582
583    /// Returns true if the container is full, otherwise false.
584    pub fn is_full(&self) -> bool {
585        self.is_full_impl()
586    }
587}
588
589/// A compile-time fixed-size, shared memory compatible [`FixedSizeSlotMap`].
590#[repr(C)]
591#[derive(Debug)]
592pub struct FixedSizeSlotMap<T, const CAPACITY: usize> {
593    state: RelocatableSlotMap<T>,
594    _idx_to_data: MaybeUninit<[usize; CAPACITY]>,
595    _idx_to_data_free_list: MaybeUninit<[FreeListEntry; CAPACITY]>,
596    _data: MaybeUninit<[Option<T>; CAPACITY]>,
597    _data_next_free_index: MaybeUninit<[usize; CAPACITY]>,
598}
599
600unsafe impl<T: ZeroCopySend, const CAPACITY: usize> ZeroCopySend for FixedSizeSlotMap<T, CAPACITY> {}
601
602impl<T, const CAPACITY: usize> PlacementDefault for FixedSizeSlotMap<T, CAPACITY> {
603    unsafe fn placement_default(ptr: *mut Self) {
604        let state_ptr = core::ptr::addr_of_mut!((*ptr).state);
605        state_ptr.write(unsafe { RelocatableSlotMap::new_uninit(CAPACITY) });
606        let allocator = BumpAllocator::new((*ptr)._idx_to_data.as_mut_ptr().cast());
607        (*ptr)
608            .state
609            .init(&allocator)
610            .expect("All required memory is preallocated.");
611    }
612}
613
614impl<T, const CAPACITY: usize> Default for FixedSizeSlotMap<T, CAPACITY> {
615    fn default() -> Self {
616        let mut new_self = Self {
617            _idx_to_data: MaybeUninit::uninit(),
618            _idx_to_data_free_list: MaybeUninit::uninit(),
619            _data: MaybeUninit::uninit(),
620            _data_next_free_index: MaybeUninit::uninit(),
621            state: unsafe { RelocatableSlotMap::new_uninit(CAPACITY) },
622        };
623
624        let allocator = BumpAllocator::new(new_self._idx_to_data.as_mut_ptr().cast());
625        unsafe {
626            new_self
627                .state
628                .init(&allocator)
629                .expect("All required memory is preallocated.")
630        };
631
632        new_self
633    }
634}
635
636impl<T, const CAPACITY: usize> FixedSizeSlotMap<T, CAPACITY> {
637    /// Creates a new empty [`FixedSizeSlotMap`].
638    pub fn new() -> Self {
639        Self::default()
640    }
641
642    /// Returns the [`RelocatableIter`]ator to iterate over all entries.
643    pub fn iter(&self) -> RelocatableIter<'_, T> {
644        unsafe { self.state.iter_impl() }
645    }
646
647    /// Returns `true` if the provided `key` is contained, otherwise `false`.
648    pub fn contains(&self, key: SlotMapKey) -> bool {
649        unsafe { self.state.contains_impl(key) }
650    }
651
652    /// Returns a reference to the value stored under the given key. If there is no such key,
653    /// [`None`] is returned.
654    pub fn get(&self, key: SlotMapKey) -> Option<&T> {
655        unsafe { self.state.get_impl(key) }
656    }
657
658    /// Returns a mutable reference to the value stored under the given key. If there is no
659    /// such key, [`None`] is returned.
660    pub fn get_mut(&mut self, key: SlotMapKey) -> Option<&mut T> {
661        unsafe { self.state.get_mut_impl(key) }
662    }
663
664    /// Insert a value and returns the corresponding [`SlotMapKey`]. If the container is full
665    /// [`None`] is returned.
666    pub fn insert(&mut self, value: T) -> Option<SlotMapKey> {
667        unsafe { self.state.insert_impl(value) }
668    }
669
670    /// Insert a value at the specified [`SlotMapKey`] and returns true.  If the provided key
671    /// is out-of-bounds it returns `false` and adds nothing. If there is already a value
672    /// stored at the `key`s index, the value is overridden with the provided value.
673    pub fn insert_at(&mut self, key: SlotMapKey, value: T) -> bool {
674        unsafe { self.state.insert_at_impl(key, value) }
675    }
676
677    /// Removes a value at the specified [`SlotMapKey`]. If there was no value corresponding
678    /// to the [`SlotMapKey`] it returns None, otherwise Some(value).
679    pub fn remove(&mut self, key: SlotMapKey) -> Option<T> {
680        unsafe { self.state.remove_impl(key) }
681    }
682
683    /// Returns the [`SlotMapKey`] that will be used when the user calls
684    /// [`SlotMap::insert()`]. If the [`SlotMap`] is full it returns [`None`].
685    pub fn next_free_key(&self) -> Option<SlotMapKey> {
686        unsafe { self.state.next_free_key_impl() }
687    }
688
689    /// Returns the number of stored values.
690    pub fn len(&self) -> usize {
691        self.state.len_impl()
692    }
693
694    /// Returns the capacity.
695    pub fn capacity(&self) -> usize {
696        self.state.capacity_impl()
697    }
698
699    /// Returns true if the container is empty, otherwise false.
700    pub fn is_empty(&self) -> bool {
701        self.state.is_empty_impl()
702    }
703
704    /// Returns true if the container is full, otherwise false.
705    pub fn is_full(&self) -> bool {
706        self.state.is_full_impl()
707    }
708}