use crate::config::Config;
#[cfg(feature = "alloc")]
use crate::config::DefaultConfig;
use crate::error::{
FullError, GetDisjointMutAtError, GetDisjointMutError, InsertError, InsertWithError,
};
use crate::key::Key;
use crate::key_layout::KeyLayout;
use crate::key_piece::KeyPiece;
use crate::storage::{ReserveStorage, SlotStorage};
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>,
}
pub 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> {
unsafe { Key::<C>::from_raw_parts(idx, self.generation.into_non_zero_unchecked()) }
}
#[inline]
unsafe fn value(&self) -> &T {
&self.data.occupied
}
#[inline]
unsafe fn value_mut(&mut self) -> &mut T {
&mut self.data.occupied
}
#[inline]
fn is_detached(&self, idx: C::Idx) -> bool {
!self.is_occupied() && unsafe { self.data.vacant } == Some(idx)
}
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 {
debug_assert!(
C::Idx::from_usize(position).is_some(),
"every slot position fits in the configured index type"
);
unsafe { C::Idx::from_usize_unchecked(position) }
}
#[inline]
unsafe fn position_of<C: Config>(idx: C::Idx) -> usize {
debug_assert!(
idx.into_usize().is_some(),
"every index of a slot fits in usize"
);
unsafe { idx.into_usize_unchecked() }
}
type Slots<T, C> = <C as Config>::Storage<Slot<T, C>>;
#[inline]
fn max_idx<C: Config>() -> C::Idx {
<C::Layout as KeyLayout<C::Idx, C::Gen>>::max_idx()
}
#[inline]
fn next_generation<C: Config>(generation: C::Gen) -> Option<C::Gen> {
if generation == <C::Layout as KeyLayout<C::Idx, C::Gen>>::max_generation() {
None
} else {
Some(generation.wrapping_add(C::Gen::ONE))
}
}
pub type StorageError<T, C> =
<<C as Config>::Storage<Slot<T, C>> as SlotStorage<Slot<T, C>>>::Error;
struct Target<C: Config> {
idx: C::Idx,
position: usize,
generation: C::Gen,
from_free_list: bool,
}
impl<C: Config> Target<C> {
#[inline]
fn key(&self) -> Key<C> {
unsafe { Key::<C>::from_raw_parts(self.idx, self.generation.into_non_zero_unchecked()) }
}
}
#[cold]
#[inline(never)]
fn panic_full<T, C: Config>(full: FullError<StorageError<T, C>>, slots_len: usize) -> ! {
match full {
FullError::IndexExhausted => panic!(
"GenMap is full, its keys can not address more than {} slots",
slots_len
),
FullError::StorageFull(error) => panic!(
"GenMap is full, its storage can not make room for more than {} slots: {:?}",
slots_len, error
),
}
}
pub struct VacantEntry<'a, T, C: Config> {
map: &'a mut GenMap<T, C>,
target: Target<C>,
}
impl<'a, T, C: Config> VacantEntry<'a, T, C> {
#[inline]
pub fn key(&self) -> Key<C> {
self.target.key()
}
#[inline]
pub fn insert(self, value: T) -> Key<C> {
unsafe { self.map.fill(self.target, value) }
}
}
impl<T, C: Config> fmt::Debug for VacantEntry<'_, T, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VacantEntry")
.field("key", &self.key())
.finish()
}
}
pub struct GenMap<
T,
#[cfg(feature = "alloc")] C: Config = DefaultConfig,
#[cfg(not(feature = "alloc"))] C: Config,
> {
slots: Slots<T, C>,
next_free: Option<C::Idx>,
len: usize,
}
#[cfg(feature = "alloc")]
impl<T> GenMap<T> {
#[inline]
pub const fn new() -> Self {
Self::new_with_config()
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self
where
Slots<T, DefaultConfig>: ReserveStorage<Slot<T, DefaultConfig>>,
{
Self {
slots: Slots::<T, DefaultConfig>::with_capacity(capacity),
next_free: None,
len: 0,
}
}
}
impl<T, C: Config> GenMap<T, C>
where
Slots<T, C>: ReserveStorage<Slot<T, C>>,
{
#[inline]
pub fn with_capacity_and_config(capacity: usize) -> Self {
Self {
slots: Slots::<T, C>::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<(), StorageError<T, C>> {
self.slots.try_reserve(additional)
}
}
impl<T, C: Config> GenMap<T, C> {
#[inline]
pub const fn new_with_config() -> Self {
Self {
slots: Slots::<T, C>::EMPTY,
next_free: None,
len: 0,
}
}
#[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.as_slice().get(key.idx().into_usize()?)?;
if slot.generation != 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.as_mut_slice().get_mut(key.idx().into_usize()?)?;
if slot.generation != 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
.as_slice()
.get_unchecked(position_of::<C>(key.idx()))
.value()
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, key: Key<C>) -> &mut T {
debug_assert!(self.contains_key(key));
self.slots
.as_mut_slice()
.get_unchecked_mut(position_of::<C>(key.idx()))
.value_mut()
}
#[inline]
pub fn key_at(&self, idx: C::Idx) -> Option<Key<C>> {
let slot = self.slots.as_slice().get(idx.into_usize()?)?;
if !slot.is_occupied() {
return None;
}
Some(unsafe { slot.key(idx) })
}
#[inline]
pub unsafe fn key_at_unchecked(&self, idx: C::Idx) -> Key<C> {
debug_assert!(self.key_at(idx).is_some());
self.slots
.as_slice()
.get_unchecked(position_of::<C>(idx))
.key(idx)
}
#[inline]
pub fn get_at(&self, idx: C::Idx) -> Option<(Key<C>, &T)> {
let slot = self.slots.as_slice().get(idx.into_usize()?)?;
if !slot.is_occupied() {
return None;
}
Some(unsafe { (slot.key(idx), slot.value()) })
}
#[inline]
pub fn get_at_mut(&mut self, idx: C::Idx) -> Option<(Key<C>, &mut T)> {
let slot = self.slots.as_mut_slice().get_mut(idx.into_usize()?)?;
if !slot.is_occupied() {
return None;
}
let key = unsafe { slot.key(idx) };
Some((key, unsafe { slot.value_mut() }))
}
#[inline]
pub unsafe fn get_at_unchecked(&self, idx: C::Idx) -> (Key<C>, &T) {
debug_assert!(self.key_at(idx).is_some());
let slot = self.slots.as_slice().get_unchecked(position_of::<C>(idx));
(slot.key(idx), slot.value())
}
#[inline]
pub unsafe fn get_at_unchecked_mut(&mut self, idx: C::Idx) -> (Key<C>, &mut T) {
debug_assert!(self.key_at(idx).is_some());
let slot = self
.slots
.as_mut_slice()
.get_unchecked_mut(position_of::<C>(idx));
let key = slot.key(idx);
(key, slot.value_mut())
}
#[inline]
pub fn generation_at(&self, idx: C::Idx) -> Option<C::Gen> {
Some(self.slots.as_slice().get(idx.into_usize()?)?.generation)
}
#[inline]
pub unsafe fn generation_at_unchecked(&self, idx: C::Idx) -> C::Gen {
debug_assert!(self.generation_at(idx).is_some());
self.slots
.as_slice()
.get_unchecked(position_of::<C>(idx))
.generation
}
#[inline]
pub fn get_disjoint_mut_at<const N: usize>(
&mut self,
idxs: [C::Idx; N],
) -> Result<[(Key<C>, &mut T); N], GetDisjointMutAtError> {
for (i, idx) in idxs.iter().enumerate() {
if self.key_at(*idx).is_none() {
return Err(GetDisjointMutAtError::NoValue);
}
if idxs[..i].contains(idx) {
return Err(GetDisjointMutAtError::OverlappingIndices);
}
}
Ok(unsafe { self.get_disjoint_mut_at_unchecked(idxs) })
}
#[inline]
pub unsafe fn get_disjoint_mut_at_unchecked<const N: usize>(
&mut self,
idxs: [C::Idx; N],
) -> [(Key<C>, &mut T); N] {
debug_assert!(idxs.iter().all(|idx| self.key_at(*idx).is_some()));
debug_assert!(idxs
.iter()
.enumerate()
.all(|(i, idx)| !idxs[..i].contains(idx)));
let slots = self.slots.as_mut_slice().as_mut_ptr();
idxs.map(|idx| {
unsafe {
let slot = slots.add(position_of::<C>(idx));
let key =
Key::<C>::from_raw_parts(idx, (*slot).generation.into_non_zero_unchecked());
(key, &mut *(*slot).data.occupied)
}
})
}
#[inline]
pub fn get_disjoint_mut<const N: usize>(
&mut self,
keys: [Key<C>; N],
) -> Result<[&mut T; N], GetDisjointMutError> {
for (i, key) in keys.iter().enumerate() {
if !self.contains_key(*key) {
return Err(GetDisjointMutError::InvalidKey);
}
if keys[..i].iter().any(|earlier| earlier.idx() == key.idx()) {
return Err(GetDisjointMutError::OverlappingKeys);
}
}
Ok(unsafe { self.get_disjoint_mut_unchecked(keys) })
}
#[inline]
pub unsafe fn get_disjoint_mut_unchecked<const N: usize>(
&mut self,
keys: [Key<C>; N],
) -> [&mut T; N] {
debug_assert!(keys.iter().all(|key| self.contains_key(*key)));
debug_assert!(keys
.iter()
.enumerate()
.all(|(i, key)| keys[..i].iter().all(|earlier| earlier.idx() != key.idx())));
let slots = self.slots.as_mut_slice().as_mut_ptr();
keys.map(|key| {
unsafe { &mut *(*slots.add(position_of::<C>(key.idx()))).data.occupied }
})
}
#[inline]
pub fn insert(&mut self, value: T) -> Key<C> {
self.insert_with_key(|_| value)
}
#[inline]
pub fn try_insert(&mut self, value: T) -> Result<Key<C>, InsertError<T, StorageError<T, C>>> {
match self.vacant_entry() {
Ok(entry) => Ok(entry.insert(value)),
Err(FullError::IndexExhausted) => Err(InsertError::IndexExhausted(value)),
Err(FullError::StorageFull(error)) => Err(InsertError::StorageFull(value, error)),
}
}
#[inline]
pub fn insert_with_key<F>(&mut self, f: F) -> Key<C>
where
F: FnOnce(Key<C>) -> T,
{
let entry = match self.vacant_entry() {
Ok(entry) => entry,
Err(full) => panic_full::<T, C>(full, self.slots.len()),
};
let value = f(entry.key());
entry.insert(value)
}
pub fn try_insert_with_key<F, E>(
&mut self,
f: F,
) -> Result<Key<C>, InsertWithError<E, StorageError<T, C>>>
where
F: FnOnce(Key<C>) -> Result<T, E>,
{
let entry = self.vacant_entry()?;
let value = f(entry.key()).map_err(InsertWithError::Rejected)?;
Ok(entry.insert(value))
}
#[inline]
pub fn vacant_entry(&mut self) -> Result<VacantEntry<'_, T, C>, FullError<StorageError<T, C>>> {
let target = self.next_target()?;
Ok(VacantEntry { map: self, target })
}
#[inline]
fn next_target(&mut self) -> Result<Target<C>, FullError<StorageError<T, C>>> {
let (idx, position, generation, from_free_list) = match self.next_free {
Some(idx) => {
let position = unsafe { position_of::<C>(idx) };
let generation =
unsafe { self.slots.as_slice().get_unchecked(position).generation };
(idx, position, generation, true)
}
None => {
let position = self.slots.len();
let idx = C::Idx::from_usize(position)
.filter(|idx| *idx <= max_idx::<C>())
.ok_or(FullError::IndexExhausted)?;
self.slots.ensure_room().map_err(FullError::StorageFull)?;
(idx, position, C::Gen::ZERO, false)
}
};
debug_assert!(!generation.is_odd());
let generation = generation.wrapping_add(C::Gen::ONE);
Ok(Target {
idx,
position,
generation,
from_free_list,
})
}
#[inline]
unsafe fn fill(&mut self, target: Target<C>, value: T) -> Key<C> {
let key = target.key();
if target.from_free_list {
let slot = unsafe { self.slots.as_mut_slice().get_unchecked_mut(target.position) };
self.next_free = unsafe { slot.data.vacant };
slot.data.occupied = ManuallyDrop::new(value);
slot.generation = target.generation;
} else {
let slot = Slot {
generation: target.generation,
data: SlotData {
occupied: ManuallyDrop::new(value),
},
};
if self.slots.try_push(slot).is_err() {
panic!("SlotStorage::try_push failed although ensure_room returned Ok");
}
}
self.len += 1;
key
}
#[inline]
pub fn remove(&mut self, key: Key<C>) -> Option<T> {
let position = key.idx().into_usize()?;
let slot = self.slots.as_slice().get(position)?;
if slot.generation != key.generation() {
return None;
}
Some(unsafe { self.take(key.idx(), position) })
}
#[inline]
pub fn retire(&mut self, key: Key<C>) -> Option<T> {
let slot = self.slots.as_mut_slice().get_mut(key.idx().into_usize()?)?;
if slot.generation != key.generation() {
return None;
}
let value = unsafe { ManuallyDrop::take(&mut slot.data.occupied) };
slot.generation = C::Gen::ZERO;
slot.data.vacant = None;
self.len -= 1;
Some(value)
}
unsafe fn take(&mut self, idx: C::Idx, position: usize) -> T {
let (slot, value) = unsafe {
let slot = self.slots.as_mut_slice().get_unchecked_mut(position);
debug_assert!(slot.is_occupied());
let value = ManuallyDrop::take(&mut slot.data.occupied);
(slot, value)
};
self.len -= 1;
match next_generation::<C>(slot.generation) {
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
}
#[inline]
pub fn detach(&mut self, key: Key<C>) -> Option<T> {
let slot = self.slots.as_mut_slice().get_mut(key.idx().into_usize()?)?;
if slot.generation != key.generation() {
return None;
}
let next = next_generation::<C>(slot.generation)?;
let value = unsafe { ManuallyDrop::take(&mut slot.data.occupied) };
slot.generation = next;
slot.data.vacant = Some(key.idx());
self.len -= 1;
Some(value)
}
#[inline]
pub fn reattach(&mut self, key: Key<C>, value: T) {
let generation = key.generation();
let slot = key
.idx()
.into_usize()
.and_then(|position| self.slots.as_mut_slice().get_mut(position))
.filter(|slot| {
next_generation::<C>(generation) == Some(slot.generation)
&& slot.is_detached(key.idx())
})
.expect("reattach on a key that is not detached");
slot.data.occupied = ManuallyDrop::new(value);
slot.generation = generation;
self.len += 1;
}
pub fn clear(&mut self) {
for position in 0..self.slots.len() {
let occupied = unsafe { self.slots.as_slice().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.as_mut_slice().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.as_slice().iter().enumerate(),
remaining: self.len,
}
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T, C> {
IterMut {
slots: self.slots.as_mut_slice().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()
}
}
fn push_cloned<T, C: Config>(slots: &mut Slots<T, C>, slot: Slot<T, C>) {
if slots.try_push(slot).is_err() {
panic!("SlotStorage::try_push failed while cloning a storage of the same type");
}
}
struct ClearOnUnwind<'a, T, C: Config>(&'a mut Slots<T, C>);
impl<T, C: Config> Drop for ClearOnUnwind<'_, T, C> {
fn drop(&mut self) {
SlotStorage::clear(self.0);
}
}
impl<T: Clone, C: Config> Clone for GenMap<T, C> {
fn clone(&self) -> Self {
let mut slots = Slots::<T, C>::with_capacity(self.slots.len());
for slot in self.slots.as_slice() {
push_cloned(&mut slots, slot.clone_slot());
}
Self {
slots,
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<'_, T, C> = ClearOnUnwind(&mut self.slots);
SlotStorage::clear(guard.0);
if guard.0.capacity() < source.slots.len() {
*guard.0 = Slots::<T, C>::with_capacity(source.slots.len());
}
for slot in source.slots.as_slice() {
push_cloned(guard.0, 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<<Slots<T, C> as IntoIterator>::IntoIter>,
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.as_slice().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() {}
}
}