use crate::config::{Config, DefaultConfig};
use crate::key::Key;
use crate::key_piece::KeyPiece;
use alloc::collections::TryReserveError;
use alloc::vec::Vec;
use core::any::type_name;
use core::fmt;
use core::iter::{Enumerate, FusedIterator};
use core::mem::ManuallyDrop;
use core::ops::{Index, IndexMut};
union SlotData<T, Idx: Copy> {
occupied: ManuallyDrop<T>,
vacant: Option<Idx>,
}
struct Slot<T, C: Config> {
generation: C::Gen,
data: SlotData<T, C::Idx>,
}
impl<T, C: Config> Slot<T, C> {
#[inline]
fn is_occupied(&self) -> bool {
self.generation.is_odd()
}
#[inline]
unsafe fn key(&self, idx: C::Idx) -> Key<C> {
Key::<C>::from_parts_unchecked(idx, self.generation)
}
#[inline]
unsafe fn value(&self) -> &T {
&self.data.occupied
}
#[inline]
unsafe fn value_mut(&mut self) -> &mut T {
&mut self.data.occupied
}
fn clone_slot(&self) -> Self
where
T: Clone,
{
let data = unsafe {
if self.is_occupied() {
SlotData {
occupied: ManuallyDrop::new(T::clone(&self.data.occupied)),
}
} else {
SlotData {
vacant: self.data.vacant,
}
}
};
Slot {
generation: self.generation,
data,
}
}
}
impl<T, C: Config> Drop for Slot<T, C> {
#[inline]
fn drop(&mut self) {
if self.is_occupied() {
unsafe { ManuallyDrop::drop(&mut self.data.occupied) }
}
}
}
#[inline]
unsafe fn index_of<C: Config>(position: usize) -> C::Idx {
let idx = C::Idx::from_usize(position);
debug_assert!(
idx.is_some(),
"every slot position fits in the configured index type"
);
unsafe { idx.unwrap_unchecked() }
}
#[inline]
unsafe fn position_of<C: Config>(idx: C::Idx) -> usize {
let position = idx.into_usize();
debug_assert!(position.is_some(), "every free list index fits in usize");
unsafe { position.unwrap_unchecked() }
}
pub struct GenMap<T, C: Config = DefaultConfig> {
slots: Vec<Slot<T, C>>,
next_free: Option<C::Idx>,
len: usize,
}
impl<T> GenMap<T> {
#[inline]
pub const fn new() -> Self {
Self::new_with_config()
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_config(capacity)
}
}
impl<T, C: Config> GenMap<T, C> {
#[inline]
pub const fn new_with_config() -> Self {
Self {
slots: Vec::new(),
next_free: None,
len: 0,
}
}
#[inline]
pub fn with_capacity_and_config(capacity: usize) -> Self {
Self {
slots: Vec::with_capacity(capacity),
next_free: None,
len: 0,
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.slots.reserve(additional);
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.slots.try_reserve(additional)
}
#[inline]
pub fn capacity(&self) -> usize {
self.slots.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn slots_len(&self) -> usize {
self.slots.len()
}
#[inline]
pub fn contains_key(&self, key: Key<C>) -> bool {
self.get(key).is_some()
}
#[inline]
pub fn get(&self, key: Key<C>) -> Option<&T> {
let slot = self.slots.get(key.idx.into_usize()?)?;
if slot.generation != C::Gen::from_non_zero(key.generation) {
return None;
}
Some(unsafe { slot.value() })
}
#[inline]
pub fn get_mut(&mut self, key: Key<C>) -> Option<&mut T> {
let slot = self.slots.get_mut(key.idx.into_usize()?)?;
if slot.generation != C::Gen::from_non_zero(key.generation) {
return None;
}
Some(unsafe { slot.value_mut() })
}
#[inline]
pub unsafe fn get_unchecked(&self, key: Key<C>) -> &T {
debug_assert!(self.contains_key(key));
self.slots
.get_unchecked(key.idx.into_usize().unwrap_unchecked())
.value()
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, key: Key<C>) -> &mut T {
debug_assert!(self.contains_key(key));
self.slots
.get_unchecked_mut(key.idx.into_usize().unwrap_unchecked())
.value_mut()
}
#[inline]
pub fn insert(&mut self, value: T) -> Key<C> {
self.insert_with_key(|_| value)
}
#[inline]
pub fn insert_with_key<F>(&mut self, f: F) -> Key<C>
where
F: FnOnce(Key<C>) -> T,
{
unsafe {
self.try_insert_with_key(|key| Ok::<T, core::convert::Infallible>(f(key)))
.unwrap_unchecked()
}
}
pub fn try_insert_with_key<F, E>(&mut self, f: F) -> Result<Key<C>, E>
where
F: FnOnce(Key<C>) -> Result<T, E>,
{
let (idx, position, generation) = match self.next_free {
Some(idx) => {
let position = unsafe { position_of::<C>(idx) };
let generation = unsafe { self.slots.get_unchecked(position).generation };
(idx, position, generation)
}
None => match C::Idx::from_usize(self.slots.len()) {
Some(idx) => (idx, self.slots.len(), C::Gen::ZERO),
None => panic!(
"GenMap is full, {} can not address more than {} slots",
type_name::<C::Idx>(),
self.slots.len()
),
},
};
debug_assert!(!generation.is_odd());
let generation = unsafe { generation.checked_add(C::Gen::ONE).unwrap_unchecked() };
let key = unsafe { Key::<C>::from_parts_unchecked(idx, generation) };
let value = f(key)?;
match self.next_free {
Some(_) => {
let slot = unsafe { self.slots.get_unchecked_mut(position) };
self.next_free = unsafe { slot.data.vacant };
slot.data.occupied = ManuallyDrop::new(value);
slot.generation = generation;
}
None => self.slots.push(Slot {
generation,
data: SlotData {
occupied: ManuallyDrop::new(value),
},
}),
}
self.len += 1;
Ok(key)
}
#[inline]
pub fn remove(&mut self, key: Key<C>) -> Option<T> {
let position = key.idx.into_usize()?;
let slot = self.slots.get(position)?;
if slot.generation != C::Gen::from_non_zero(key.generation) {
return None;
}
Some(unsafe { self.take(key.idx, position) })
}
unsafe fn take(&mut self, idx: C::Idx, position: usize) -> T {
let (slot, value) = unsafe {
let slot = self.slots.get_unchecked_mut(position);
debug_assert!(slot.is_occupied());
let value = ManuallyDrop::take(&mut slot.data.occupied);
(slot, value)
};
self.len -= 1;
match slot.generation.checked_add(C::Gen::ONE) {
Some(next) => {
slot.generation = next;
slot.data.vacant = self.next_free;
self.next_free = Some(idx);
}
None => {
slot.generation = C::Gen::ZERO;
if C::WRAP_ON_OVERFLOW {
slot.data.vacant = self.next_free;
self.next_free = Some(idx);
} else {
slot.data.vacant = None;
}
}
}
value
}
pub fn clear(&mut self) {
for position in 0..self.slots.len() {
let occupied = unsafe { self.slots.get_unchecked(position).is_occupied() };
if occupied {
drop(unsafe { self.take(index_of::<C>(position), position) });
}
}
debug_assert_eq!(self.len, 0);
}
#[inline]
pub fn reset(&mut self) {
self.next_free = None;
self.len = 0;
self.slots.clear();
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(Key<C>, &mut T) -> bool,
{
for position in 0..self.slots.len() {
let slot = unsafe { self.slots.get_unchecked_mut(position) };
if !slot.is_occupied() {
continue;
}
let (idx, keep) = unsafe {
let idx = index_of::<C>(position);
(idx, f(slot.key(idx), slot.value_mut()))
};
if !keep {
drop(unsafe { self.take(idx, position) });
}
}
}
#[inline]
pub fn drain(&mut self) -> Drain<'_, T, C> {
Drain {
map: self,
position: 0,
}
}
#[inline]
pub fn iter(&self) -> Iter<'_, T, C> {
Iter {
slots: self.slots.iter().enumerate(),
remaining: self.len,
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T, C> {
IterMut {
slots: self.slots.iter_mut().enumerate(),
remaining: self.len,
}
}
#[inline]
pub fn keys(&self) -> Keys<'_, T, C> {
Keys { inner: self.iter() }
}
#[inline]
pub fn values(&self) -> Values<'_, T, C> {
Values { inner: self.iter() }
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, T, C> {
ValuesMut {
inner: self.iter_mut(),
}
}
}
impl<T, C: Config> Default for GenMap<T, C> {
#[inline]
fn default() -> Self {
Self::new_with_config()
}
}
impl<T, C: Config> Index<Key<C>> for GenMap<T, C> {
type Output = T;
#[inline]
fn index(&self, key: Key<C>) -> &T {
self.get(key).expect("invalid GenMap key")
}
}
impl<T, C: Config> IndexMut<Key<C>> for GenMap<T, C> {
#[inline]
fn index_mut(&mut self, key: Key<C>) -> &mut T {
self.get_mut(key).expect("invalid GenMap key")
}
}
impl<T: fmt::Debug, C: Config> fmt::Debug for GenMap<T, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
struct ClearOnUnwind<'a, T, C: Config>(&'a mut Vec<Slot<T, C>>);
impl<T, C: Config> Drop for ClearOnUnwind<'_, T, C> {
fn drop(&mut self) {
self.0.clear();
}
}
impl<T: Clone, C: Config> Clone for GenMap<T, C> {
fn clone(&self) -> Self {
Self {
slots: self.slots.iter().map(Slot::clone_slot).collect(),
next_free: self.next_free,
len: self.len,
}
}
fn clone_from(&mut self, source: &Self) {
self.next_free = None;
self.len = 0;
let guard = ClearOnUnwind(&mut self.slots);
guard.0.clear();
guard.0.extend(source.slots.iter().map(Slot::clone_slot));
core::mem::forget(guard);
self.next_free = source.next_free;
self.len = source.len;
}
}
pub struct Iter<'a, T, C: Config> {
slots: Enumerate<core::slice::Iter<'a, Slot<T, C>>>,
remaining: usize,
}
impl<'a, T, C: Config> Iterator for Iter<'a, T, C> {
type Item = (Key<C>, &'a T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (position, slot) in self.slots.by_ref() {
if slot.is_occupied() {
self.remaining -= 1;
return unsafe { Some((slot.key(index_of::<C>(position)), slot.value())) };
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, C: Config> DoubleEndedIterator for Iter<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((position, slot)) = self.slots.next_back() {
if slot.is_occupied() {
self.remaining -= 1;
return unsafe { Some((slot.key(index_of::<C>(position)), slot.value())) };
}
}
None
}
}
impl<T, C: Config> ExactSizeIterator for Iter<'_, T, C> {}
impl<T, C: Config> FusedIterator for Iter<'_, T, C> {}
impl<T, C: Config> Clone for Iter<'_, T, C> {
fn clone(&self) -> Self {
Self {
slots: self.slots.clone(),
remaining: self.remaining,
}
}
}
pub struct IterMut<'a, T, C: Config> {
slots: Enumerate<core::slice::IterMut<'a, Slot<T, C>>>,
remaining: usize,
}
impl<'a, T, C: Config> Iterator for IterMut<'a, T, C> {
type Item = (Key<C>, &'a mut T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (position, slot) in self.slots.by_ref() {
if slot.is_occupied() {
self.remaining -= 1;
return unsafe { Some((slot.key(index_of::<C>(position)), slot.value_mut())) };
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, C: Config> DoubleEndedIterator for IterMut<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((position, slot)) = self.slots.next_back() {
if slot.is_occupied() {
self.remaining -= 1;
return unsafe { Some((slot.key(index_of::<C>(position)), slot.value_mut())) };
}
}
None
}
}
impl<T, C: Config> ExactSizeIterator for IterMut<'_, T, C> {}
impl<T, C: Config> FusedIterator for IterMut<'_, T, C> {}
pub struct Keys<'a, T, C: Config> {
inner: Iter<'a, T, C>,
}
impl<T, C: Config> Iterator for Keys<'_, T, C> {
type Item = Key<C>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(key, _)| key)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T, C: Config> DoubleEndedIterator for Keys<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(key, _)| key)
}
}
impl<T, C: Config> ExactSizeIterator for Keys<'_, T, C> {}
impl<T, C: Config> FusedIterator for Keys<'_, T, C> {}
impl<T, C: Config> Clone for Keys<'_, T, C> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
pub struct Values<'a, T, C: Config> {
inner: Iter<'a, T, C>,
}
impl<'a, T, C: Config> Iterator for Values<'a, T, C> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(_, value)| value)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T, C: Config> DoubleEndedIterator for Values<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(_, value)| value)
}
}
impl<T, C: Config> ExactSizeIterator for Values<'_, T, C> {}
impl<T, C: Config> FusedIterator for Values<'_, T, C> {}
impl<T, C: Config> Clone for Values<'_, T, C> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
pub struct ValuesMut<'a, T, C: Config> {
inner: IterMut<'a, T, C>,
}
impl<'a, T, C: Config> Iterator for ValuesMut<'a, T, C> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|(_, value)| value)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T, C: Config> DoubleEndedIterator for ValuesMut<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(_, value)| value)
}
}
impl<T, C: Config> ExactSizeIterator for ValuesMut<'_, T, C> {}
impl<T, C: Config> FusedIterator for ValuesMut<'_, T, C> {}
pub struct IntoIter<T, C: Config> {
slots: Enumerate<alloc::vec::IntoIter<Slot<T, C>>>,
remaining: usize,
}
impl<T, C: Config> Iterator for IntoIter<T, C> {
type Item = (Key<C>, T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (position, mut slot) in self.slots.by_ref() {
if slot.is_occupied() {
self.remaining -= 1;
unsafe {
let key = slot.key(index_of::<C>(position));
let value = ManuallyDrop::take(&mut slot.data.occupied);
slot.generation = C::Gen::ZERO;
return Some((key, value));
}
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, C: Config> DoubleEndedIterator for IntoIter<T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((position, mut slot)) = self.slots.next_back() {
if slot.is_occupied() {
self.remaining -= 1;
unsafe {
let key = slot.key(index_of::<C>(position));
let value = ManuallyDrop::take(&mut slot.data.occupied);
slot.generation = C::Gen::ZERO;
return Some((key, value));
}
}
}
None
}
}
impl<T, C: Config> ExactSizeIterator for IntoIter<T, C> {}
impl<T, C: Config> FusedIterator for IntoIter<T, C> {}
impl<T, C: Config> IntoIterator for GenMap<T, C> {
type Item = (Key<C>, T);
type IntoIter = IntoIter<T, C>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
remaining: self.len,
slots: self.slots.into_iter().enumerate(),
}
}
}
impl<'a, T, C: Config> IntoIterator for &'a GenMap<T, C> {
type Item = (Key<C>, &'a T);
type IntoIter = Iter<'a, T, C>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, C: Config> IntoIterator for &'a mut GenMap<T, C> {
type Item = (Key<C>, &'a mut T);
type IntoIter = IterMut<'a, T, C>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
pub struct Drain<'a, T, C: Config> {
map: &'a mut GenMap<T, C>,
position: usize,
}
impl<T, C: Config> Iterator for Drain<'_, T, C> {
type Item = (Key<C>, T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
while self.position < self.map.slots.len() {
let position = self.position;
self.position += 1;
let slot = unsafe { self.map.slots.get_unchecked(position) };
if slot.is_occupied() {
unsafe {
let idx = index_of::<C>(position);
let key = slot.key(idx);
return Some((key, self.map.take(idx, position)));
}
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.map.len, Some(self.map.len))
}
}
impl<T, C: Config> ExactSizeIterator for Drain<'_, T, C> {}
impl<T, C: Config> FusedIterator for Drain<'_, T, C> {}
impl<T, C: Config> Drop for Drain<'_, T, C> {
fn drop(&mut self) {
for _ in self.by_ref() {}
}
}