use crate::handle::Handle;
use crate::slot::SlotContent::Occupied;
use crate::slot::SlotContentMut::OccupiedMut;
use crate::slot::{Slot, SlotUnion};
use crate::utils::{likely, unlikely};
use std::mem::ManuallyDrop;
#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicU64, Ordering};
#[cfg(debug_assertions)]
static NEXT_MAP_ID: AtomicU64 = AtomicU64::new(0);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DeferredMap<T, K: crate::Key = crate::DefaultKey> {
slots: Vec<Slot<T>>,
free_head: u32, num_elems: u32, #[cfg(debug_assertions)]
map_id: u64,
#[cfg_attr(feature = "serde", serde(skip))]
_marker: std::marker::PhantomData<K>,
}
impl<T> DeferredMap<T, crate::DefaultKey> {
#[inline(always)]
pub fn new() -> Self {
Self::with_capacity(0)
}
}
impl<T, K: crate::Key> DeferredMap<T, K> {
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
let mut slots = Vec::with_capacity(capacity + 1);
slots.push(Slot {
u: SlotUnion { next_free: 0 },
version: crate::Version::sentinel(),
});
Self {
slots,
free_head: 1, num_elems: 0,
#[cfg(debug_assertions)]
map_id: NEXT_MAP_ID.fetch_add(1, Ordering::Relaxed),
_marker: std::marker::PhantomData,
}
}
pub fn allocate_handle(&mut self) -> Handle<K> {
if let Some(slot) = self.slots.get_mut(self.free_head as usize) {
let index = self.free_head;
unsafe {
self.free_head = slot.u.next_free;
}
slot.version.vacant_to_reserved();
let key = K::from_parts(
index,
slot.generation(),
#[cfg(debug_assertions)]
self.map_id,
);
Handle::new(key)
} else {
let index = self.slots.len() as u32;
let version = crate::Version::new(crate::Generation::MIN, 0b01);
self.slots.push(Slot {
u: SlotUnion { next_free: 0 }, version,
});
self.free_head = index + 1;
let key = K::from_parts(
index,
version.generation(),
#[cfg(debug_assertions)]
self.map_id,
);
Handle::new(key)
}
}
pub fn insert(&mut self, handle: Handle<K>, value: T) {
#[cfg(debug_assertions)]
debug_assert_eq!(
self.map_id,
handle.key.map_id(),
"Handle used with wrong map instance"
);
let index = handle.index();
debug_assert!(index != 0, "Invalid handle: sentinel index");
debug_assert!(
(index as usize) < self.slots.len(),
"Invalid handle: index out of bounds"
);
let slot = unsafe { self.slots.get_unchecked_mut(index as usize) };
debug_assert!(
slot.generation() == handle.generation(),
"Generation mismatch"
);
debug_assert!(slot.is_reserved(), "Handle already used or invalid state");
slot.u.value = ManuallyDrop::new(value);
slot.version.reserved_to_occupied();
self.num_elems += 1;
}
#[inline]
pub fn get(&self, key: K) -> Option<&T> {
#[cfg(debug_assertions)]
debug_assert_eq!(
self.map_id,
key.map_id(),
"Key used with wrong map instance"
);
let index = key.index();
let generation = key.generation();
if unlikely(index as usize >= self.slots.len()) {
return None;
}
let slot = unsafe { self.slots.get_unchecked(index as usize) };
if likely(slot.generation() == generation && slot.is_occupied()) {
Some(unsafe { &*slot.u.value })
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self, key: K) -> Option<&mut T> {
#[cfg(debug_assertions)]
debug_assert_eq!(
self.map_id,
key.map_id(),
"Key used with wrong map instance"
);
let index = key.index();
let generation = key.generation();
if unlikely(index as usize >= self.slots.len()) {
return None;
}
let slot = unsafe { self.slots.get_unchecked_mut(index as usize) };
if likely(slot.generation() == generation && slot.is_occupied()) {
Some(unsafe { &mut *slot.u.value })
} else {
None
}
}
#[inline]
pub fn remove(&mut self, key: K) -> Option<T> {
#[cfg(debug_assertions)]
debug_assert_eq!(
self.map_id,
key.map_id(),
"Key used with wrong map instance"
);
let index = key.index();
let generation = key.generation();
if unlikely(index as usize >= self.slots.len()) {
return None;
}
let slot = unsafe { self.slots.get_unchecked_mut(index as usize) };
if likely(slot.generation() == generation && slot.is_occupied()) {
let value = unsafe { ManuallyDrop::take(&mut slot.u.value) };
slot.u.next_free = self.free_head;
self.free_head = index;
slot.version.occupied_to_vacant();
self.num_elems -= 1;
Some(value)
} else {
None
}
}
pub fn release_handle(&mut self, handle: Handle<K>) {
#[cfg(debug_assertions)]
debug_assert_eq!(
self.map_id,
handle.key.map_id(),
"Handle used with wrong map instance"
);
let index = handle.index();
let handle_generation = handle.generation();
debug_assert!(index != 0, "Invalid handle: sentinel index");
debug_assert!(
(index as usize) < self.slots.len(),
"Invalid handle: index out of bounds"
);
let slot = &mut self.slots[index as usize];
debug_assert!(
slot.generation() == handle_generation,
"Generation mismatch"
);
debug_assert!(slot.is_reserved(), "Handle already used or invalid state");
slot.u.next_free = self.free_head;
self.free_head = index;
slot.version.reserved_to_vacant();
}
#[inline]
pub fn contains_key(&self, key: K) -> bool {
self.get(key).is_some()
}
#[inline]
pub fn len(&self) -> usize {
self.num_elems as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.num_elems == 0
}
#[inline]
pub fn capacity(&self) -> usize {
self.slots.capacity().saturating_sub(1)
}
#[inline]
pub fn clear(&mut self) {
self.slots.clear();
self.slots.push(Slot {
u: SlotUnion { next_free: 0 },
version: crate::Version::sentinel(),
});
self.free_head = 1;
self.num_elems = 0;
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (K, &T)> {
self.slots
.iter()
.enumerate()
.skip(1)
.filter_map(|(index, slot)| {
if let Occupied(value) = slot.get() {
let key = K::from_parts(
index as u32,
slot.generation(),
#[cfg(debug_assertions)]
self.map_id,
);
Some((key, value))
} else {
None
}
})
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = (K, &mut T)> {
#[cfg(debug_assertions)]
let map_id = self.map_id;
self.slots
.iter_mut()
.enumerate()
.skip(1)
.filter_map(move |(index, slot)| {
let generation = slot.generation();
if let OccupiedMut(value) = slot.get_mut() {
let key = K::from_parts(
index as u32,
generation,
#[cfg(debug_assertions)]
map_id,
);
Some((key, value))
} else {
None
}
})
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.slots.reserve(additional);
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.slots.shrink_to_fit();
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(K, &mut T) -> bool,
{
for i in 1..self.slots.len() {
let slot = unsafe { self.slots.get_unchecked_mut(i) };
if slot.is_occupied() {
let generation = slot.generation();
let key = K::from_parts(
i as u32,
generation,
#[cfg(debug_assertions)]
self.map_id,
);
let value = unsafe { &mut *slot.u.value };
if !f(key, value) {
unsafe { ManuallyDrop::drop(&mut slot.u.value) };
slot.u.next_free = self.free_head;
self.free_head = i as u32;
slot.version.occupied_to_vacant();
self.num_elems -= 1;
}
}
}
}
}
impl<T: Clone, K: crate::Key> Clone for DeferredMap<T, K> {
#[inline]
fn clone(&self) -> Self {
Self {
slots: self.slots.clone(),
free_head: self.free_head,
num_elems: self.num_elems,
#[cfg(debug_assertions)]
map_id: NEXT_MAP_ID.fetch_add(1, Ordering::Relaxed),
_marker: std::marker::PhantomData,
}
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.slots.clone_from(&source.slots);
self.free_head = source.free_head;
self.num_elems = source.num_elems;
#[cfg(debug_assertions)]
{
self.map_id = NEXT_MAP_ID.fetch_add(1, Ordering::Relaxed);
}
}
}
impl<T> Default for DeferredMap<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod basic_tests {
use super::*;
#[test]
fn test_basic_insert_and_get() {
let mut map = DeferredMap::new();
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, 42);
assert_eq!(map.get(key), Some(&42));
}
#[test]
fn test_remove_and_reuse() {
let mut map = DeferredMap::new();
let handle1 = map.allocate_handle();
let key1 = handle1.key();
map.insert(handle1, 42);
assert_eq!(map.len(), 1);
assert_eq!(map.remove(key1), Some(42));
assert_eq!(map.len(), 0);
assert_eq!(map.get(key1), None);
let handle2 = map.allocate_handle();
let key2 = handle2.key();
map.insert(handle2, 100);
assert_ne!(key1, key2);
assert_eq!(map.get(key2), Some(&100));
assert_eq!(map.get(key1), None); }
#[test]
fn test_multiple_inserts() {
let mut map = DeferredMap::new();
let mut keys = Vec::new();
for i in 0..10 {
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, i * 10);
keys.push(key);
}
assert_eq!(map.len(), 10);
for (i, &key) in keys.iter().enumerate() {
assert_eq!(map.get(key), Some(&(i * 10)));
}
}
#[test]
fn test_get_mut() {
let mut map = DeferredMap::new();
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, 42);
if let Some(value) = map.get_mut(key) {
*value = 100;
}
assert_eq!(map.get(key), Some(&100));
}
#[test]
fn test_contains_key() {
let mut map = DeferredMap::new();
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, 42);
assert!(map.contains_key(key));
map.remove(key);
assert!(!map.contains_key(key));
}
#[test]
fn test_is_empty() {
let mut map: DeferredMap<i32> = DeferredMap::new();
assert!(map.is_empty());
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, 42);
assert!(!map.is_empty());
map.remove(key);
assert!(map.is_empty());
}
#[test]
fn test_capacity() {
let mut map: DeferredMap<i32> = DeferredMap::with_capacity(10);
for _ in 0..5 {
let handle = map.allocate_handle();
map.insert(handle, 42);
}
assert_eq!(map.len(), 5);
assert!(map.capacity() >= 5);
}
#[test]
fn test_clear() {
let mut map = DeferredMap::new();
for i in 0..5 {
let handle = map.allocate_handle();
map.insert(handle, i);
}
assert_eq!(map.len(), 5);
map.clear();
assert_eq!(map.len(), 0);
assert!(map.capacity() >= 5);
assert!(map.is_empty());
}
#[test]
fn test_iter() {
let mut map = DeferredMap::new();
let mut keys = Vec::new();
for i in 0..5 {
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, i * 10);
keys.push(key);
}
let collected: Vec<_> = map.iter().collect();
assert_eq!(collected.len(), 5);
for (key, &value) in map.iter() {
assert!(keys.contains(&key));
let index = keys.iter().position(|&k| k == key).unwrap();
assert_eq!(value, index * 10);
}
}
#[test]
fn test_iter_mut() {
let mut map = DeferredMap::new();
for i in 0..5 {
let handle = map.allocate_handle();
map.insert(handle, i);
}
for (_, value) in map.iter_mut() {
*value *= 2;
}
for (_, &value) in map.iter() {
assert_eq!(value % 2, 0);
}
}
#[test]
fn test_handle_encoding_decoding() {
let mut map: DeferredMap<i32> = DeferredMap::new();
let handle = map.allocate_handle();
let key = handle.key();
let index = handle.index();
let generation = handle.generation();
let expected_key = crate::DefaultKey::new(
index,
generation,
#[cfg(debug_assertions)]
key.map_id,
);
assert_eq!(expected_key.raw, key.raw);
assert_eq!(key.decode(), (index, generation));
}
#[test]
fn test_stress_test() {
let mut map = DeferredMap::new();
let mut keys = Vec::new();
for i in 0..100 {
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, i);
keys.push(key);
}
assert_eq!(map.len(), 100);
for i in (0..100).step_by(2) {
map.remove(keys[i]);
}
assert_eq!(map.len(), 50);
for i in 0..50 {
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, i + 1000);
keys[i * 2] = key; }
assert_eq!(map.len(), 100);
let mut count = 0;
for (_, _) in map.iter() {
count += 1;
}
assert_eq!(count, 100);
}
#[test]
fn test_generation_wrapping() {
let mut map = DeferredMap::new();
let mut keys = Vec::new();
for i in 0..10 {
let handle = map.allocate_handle();
let key = handle.key();
map.insert(handle, i);
keys.push(key);
}
for key in &keys {
map.remove(*key);
}
let handle = map.allocate_handle();
let new_key = handle.key();
map.insert(handle, 100);
assert_eq!(map.get(keys[0]), None);
assert_eq!(map.get(new_key), Some(&100));
}
}