#[cfg(feature = "alloc")]
use crate::config::DefaultMapConfig;
use crate::config::{GenMapConfig, KeyConfig, MapConfig, MapConfigFor};
use crate::error::{
FullError, GetDisjointMutAtError, GetDisjointMutError, InsertError, InsertWithError,
};
use crate::key::Key;
use crate::key_piece::KeyPiece;
use crate::parity::{Even, Odd};
use crate::slot::{Parity, Slot};
use crate::storage::{ReserveStorage, SlotStorage};
use core::fmt;
use core::iter::{Enumerate, FusedIterator};
use core::ops::{Index, IndexMut};
pub type MapKeyConfig<C> = <C as MapConfig>::KeyConfig;
pub type MapIdx<C> = <MapKeyConfig<C> as KeyConfig>::Idx;
pub type MapGen<C> = <MapKeyConfig<C> as KeyConfig>::Gen;
pub(crate) type Idx<C> = MapIdx<C>;
pub(crate) type Gen<C> = MapGen<C>;
pub type MapSlot<T, C> = Slot<MapGen<C>, T, MapIdx<C>>;
#[inline]
unsafe fn slot_key<C: MapConfig>(idx: Idx<C>, generation: Odd<Gen<C>>) -> Key<MapKeyConfig<C>> {
Key::from_repr(unsafe { <MapKeyConfig<C> as KeyConfig>::pack_unchecked(idx, generation) })
}
#[inline]
unsafe fn index_of<C: MapConfig>(position: usize) -> Idx<C> {
debug_assert!(
Idx::<C>::from_usize(position).is_some(),
"every slot position fits in the configured index type"
);
unsafe { Idx::<C>::from_usize_unchecked(position) }
}
#[inline]
unsafe fn position_of<C: MapConfig>(idx: Idx<C>) -> 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 GenMapConfig<MapSlot<T, C>>>::Storage;
#[inline]
fn max_idx<C: MapConfig>() -> Idx<C> {
<MapKeyConfig<C> as KeyConfig>::max_idx()
}
#[inline]
fn max_slot_idx<C: MapConfig>() -> Idx<C> {
let max = max_idx::<C>();
if max == Idx::<C>::MAX {
max.wrapping_sub(Idx::<C>::ONE)
} else {
max
}
}
#[inline]
fn no_slot<C: MapConfig>() -> Idx<C> {
Idx::<C>::MAX
}
#[inline]
pub(crate) fn increment_len<I: KeyPiece>(len: &mut I) {
debug_assert!(
*len < I::MAX,
"a map never holds as many values as the largest value of its index type"
);
*len = len.wrapping_add(I::ONE);
}
#[inline]
pub(crate) fn decrement_len<I: KeyPiece>(len: &mut I) {
debug_assert!(*len > I::ZERO, "a map only removes a value it holds");
*len = len.wrapping_sub(I::ONE);
}
#[inline]
fn next_generation<C: MapConfig>(generation: Odd<Gen<C>>) -> Option<Even<Gen<C>>> {
if generation == <MapKeyConfig<C> as KeyConfig>::max_generation() {
None
} else {
Some(generation.wrapping_next())
}
}
#[inline]
fn detached_generation<C: MapConfig>(generation: Odd<Gen<C>>) -> Even<Gen<C>> {
generation.wrapping_next()
}
pub type StorageError<T, C> = <<C as GenMapConfig<MapSlot<T, C>>>::Storage as SlotStorage>::Error;
struct Target<C: MapConfig> {
idx: Idx<C>,
position: usize,
generation: Odd<Gen<C>>,
from_free_list: bool,
}
impl<C: MapConfig> Target<C> {
#[inline]
fn key(&self) -> Key<MapKeyConfig<C>> {
Key::from_repr(unsafe {
<MapKeyConfig<C> as KeyConfig>::pack_unchecked(self.idx, self.generation)
})
}
}
#[cold]
#[inline(never)]
fn panic_full<T, C: MapConfigFor<T>>(full: FullError<StorageError<T, C>>, slots_len: usize) -> ! {
match full {
FullError::IndexExhausted => panic!(
"GenMap is full, its keys cannot address more than {} slots",
slots_len
),
FullError::StorageFull(error) => panic!(
"GenMap is full, its storage cannot make room for more than {} slots: {:?}",
slots_len, error
),
}
}
pub struct VacantEntry<'a, T, C: MapConfigFor<T>> {
map: &'a mut GenMap<T, C>,
target: Target<C>,
}
impl<'a, T, C: MapConfigFor<T>> VacantEntry<'a, T, C> {
#[inline]
pub fn key(&self) -> Key<MapKeyConfig<C>> {
self.target.key()
}
#[inline]
pub fn insert(self, value: T) -> Key<MapKeyConfig<C>> {
unsafe { self.map.fill(self.target, value) }
}
}
impl<T, C: MapConfigFor<T>> 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: MapConfigFor<T> = DefaultMapConfig,
#[cfg(not(feature = "alloc"))] C: MapConfigFor<T>,
> {
slots: Slots<T, C>,
next_free: Idx<C>,
len: Idx<C>,
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<T> GenMap<T> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self::new_with_config()
}
#[inline]
#[must_use]
pub fn with_capacity(capacity: usize) -> Self
where
Slots<T, DefaultMapConfig>: ReserveStorage,
{
Self::with_slots(Slots::<T, DefaultMapConfig>::with_capacity(capacity))
}
}
impl<T, C: MapConfigFor<T>> GenMap<T, C>
where
Slots<T, C>: ReserveStorage,
{
#[inline]
#[must_use]
pub fn with_capacity_and_config(capacity: usize) -> Self {
Self::with_slots(Slots::<T, C>::with_capacity(capacity))
}
#[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: MapConfigFor<T>> GenMap<T, C> {
#[inline]
#[must_use]
pub fn new_with_config() -> Self {
Self::with_slots(Slots::<T, C>::empty())
}
#[inline]
fn with_slots(slots: Slots<T, C>) -> Self {
debug_assert!(slots.as_slice().is_empty());
Self {
slots,
next_free: no_slot::<C>(),
len: Idx::<C>::ZERO,
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.slots.capacity()
}
#[inline]
pub fn len(&self) -> usize {
unsafe { self.len.into_usize_unchecked() }
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == Idx::<C>::ZERO
}
#[inline]
pub fn slots_len(&self) -> usize {
self.slots.len()
}
#[inline]
pub fn contains_key(&self, key: Key<MapKeyConfig<C>>) -> bool {
self.get(key).is_some()
}
#[inline]
pub fn get(&self, key: Key<MapKeyConfig<C>>) -> Option<&T> {
self.slots
.as_slice()
.get(key.idx().into_usize()?)?
.get_odd(key.generation())
}
#[inline]
pub fn get_mut(&mut self, key: Key<MapKeyConfig<C>>) -> Option<&mut T> {
self.slots
.as_mut_slice()
.get_mut(key.idx().into_usize()?)?
.get_odd_mut(key.generation())
}
#[inline]
pub unsafe fn get_unchecked(&self, key: Key<MapKeyConfig<C>>) -> &T {
debug_assert!(self.contains_key(key));
unsafe {
self.slots
.as_slice()
.get_unchecked(position_of::<C>(key.idx()))
.get_odd_unchecked()
}
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, key: Key<MapKeyConfig<C>>) -> &mut T {
debug_assert!(self.contains_key(key));
unsafe {
self.slots
.as_mut_slice()
.get_unchecked_mut(position_of::<C>(key.idx()))
.get_odd_unchecked_mut()
}
}
#[inline]
pub fn key_at(&self, idx: MapIdx<C>) -> Option<Key<MapKeyConfig<C>>> {
match self.slots.as_slice().get(idx.into_usize()?)?.as_parity() {
Parity::Odd(generation, _) => Some(unsafe { slot_key::<C>(idx, generation) }),
Parity::Even(..) => None,
}
}
#[inline]
pub unsafe fn key_at_unchecked(&self, idx: MapIdx<C>) -> Key<MapKeyConfig<C>> {
debug_assert!(self.key_at(idx).is_some());
unsafe {
let slot = self.slots.as_slice().get_unchecked(position_of::<C>(idx));
slot_key::<C>(idx, Odd::new_unchecked(slot.generation()))
}
}
#[inline]
pub fn get_at(&self, idx: MapIdx<C>) -> Option<(Key<MapKeyConfig<C>>, &T)> {
match self.slots.as_slice().get(idx.into_usize()?)?.as_parity() {
Parity::Odd(generation, value) => {
Some((unsafe { slot_key::<C>(idx, generation) }, value))
}
Parity::Even(..) => None,
}
}
#[inline]
pub fn get_at_mut(&mut self, idx: MapIdx<C>) -> Option<(Key<MapKeyConfig<C>>, &mut T)> {
match self
.slots
.as_mut_slice()
.get_mut(idx.into_usize()?)?
.as_parity_mut()
{
Parity::Odd(generation, value) => {
Some((unsafe { slot_key::<C>(idx, generation) }, value))
}
Parity::Even(..) => None,
}
}
#[inline]
pub unsafe fn get_at_unchecked(&self, idx: MapIdx<C>) -> (Key<MapKeyConfig<C>>, &T) {
debug_assert!(self.key_at(idx).is_some());
unsafe {
let slot = self.slots.as_slice().get_unchecked(position_of::<C>(idx));
(
slot_key::<C>(idx, Odd::new_unchecked(slot.generation())),
slot.get_odd_unchecked(),
)
}
}
#[inline]
pub unsafe fn get_at_unchecked_mut(
&mut self,
idx: MapIdx<C>,
) -> (Key<MapKeyConfig<C>>, &mut T) {
debug_assert!(self.key_at(idx).is_some());
unsafe {
let slot = self
.slots
.as_mut_slice()
.get_unchecked_mut(position_of::<C>(idx));
let key = slot_key::<C>(idx, Odd::new_unchecked(slot.generation()));
(key, slot.get_odd_unchecked_mut())
}
}
#[inline]
pub fn generation_at(&self, idx: MapIdx<C>) -> Option<MapGen<C>> {
Some(self.slots.as_slice().get(idx.into_usize()?)?.generation())
}
#[inline]
pub unsafe fn generation_at_unchecked(&self, idx: MapIdx<C>) -> MapGen<C> {
debug_assert!(self.generation_at(idx).is_some());
unsafe {
self.slots
.as_slice()
.get_unchecked(position_of::<C>(idx))
.generation()
}
}
#[inline]
#[allow(clippy::type_complexity)]
pub fn get_disjoint_mut_at<const N: usize>(
&mut self,
idxs: [MapIdx<C>; N],
) -> Result<[(Key<MapKeyConfig<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: [MapIdx<C>; N],
) -> [(Key<MapKeyConfig<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 = &mut *slots.add(position_of::<C>(idx));
let key = slot_key::<C>(idx, Odd::new_unchecked(slot.generation()));
(key, slot.get_odd_unchecked_mut())
}
})
}
#[inline]
pub fn get_disjoint_mut<const N: usize>(
&mut self,
keys: [Key<MapKeyConfig<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<MapKeyConfig<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 { (*slots.add(position_of::<C>(key.idx()))).get_odd_unchecked_mut() }
})
}
#[inline]
pub fn insert(&mut self, value: T) -> Key<MapKeyConfig<C>> {
self.insert_with_key(|_| value)
}
#[inline]
#[allow(clippy::type_complexity)]
pub fn try_insert(
&mut self,
value: T,
) -> Result<Key<MapKeyConfig<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<MapKeyConfig<C>>
where
F: FnOnce(Key<MapKeyConfig<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)
}
#[allow(clippy::type_complexity)]
pub fn try_insert_with_key<F, E>(
&mut self,
f: F,
) -> Result<Key<MapKeyConfig<C>>, InsertWithError<E, StorageError<T, C>>>
where
F: FnOnce(Key<MapKeyConfig<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) = if self.next_free != no_slot::<C>() {
let idx = self.next_free;
let (position, generation) = unsafe {
let position = position_of::<C>(idx);
let slot = self.slots.as_slice().get_unchecked(position);
(position, Even::new_unchecked(slot.generation()))
};
(idx, position, generation, true)
} else {
let position = self.slots.len();
let idx = Idx::<C>::from_usize(position)
.filter(|idx| *idx <= max_slot_idx::<C>())
.ok_or(FullError::IndexExhausted)?;
self.slots.ensure_room(1).map_err(FullError::StorageFull)?;
(idx, position, Even::ZERO, false)
};
let generation = generation.next();
Ok(Target {
idx,
position,
generation,
from_free_list,
})
}
#[inline]
unsafe fn fill(&mut self, target: Target<C>, value: T) -> Key<MapKeyConfig<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.replace_even_unchecked(target.generation, value) };
} else {
let slot = Slot::new_odd(target.generation, value);
if self.slots.try_push(slot).is_err() {
panic!("SlotStorage::try_push failed although ensure_room returned Ok");
}
}
increment_len(&mut self.len);
key
}
#[inline]
pub fn remove(&mut self, key: Key<MapKeyConfig<C>>) -> Option<T> {
let position = key.idx().into_usize()?;
self.slots
.as_slice()
.get(position)?
.get_odd(key.generation())?;
Some(unsafe { self.take(key.idx(), position) })
}
#[inline]
pub fn retire(&mut self, key: Key<MapKeyConfig<C>>) -> Option<T> {
let slot = self.slots.as_mut_slice().get_mut(key.idx().into_usize()?)?;
slot.get_odd(key.generation())?;
decrement_len(&mut self.len);
Some(unsafe { slot.replace_odd_unchecked(Even::ZERO, no_slot::<C>()) })
}
unsafe fn take(&mut self, idx: Idx<C>, position: usize) -> T {
let (slot, generation) = unsafe {
let slot = self.slots.as_mut_slice().get_unchecked_mut(position);
let generation = Odd::new_unchecked(slot.generation());
(slot, generation)
};
decrement_len(&mut self.len);
let (next, link) = match next_generation::<C>(generation) {
Some(next) => (next, core::mem::replace(&mut self.next_free, idx)),
None if <C as GenMapConfig<MapSlot<T, C>>>::WRAP_ON_OVERFLOW => {
(Even::ZERO, core::mem::replace(&mut self.next_free, idx))
}
None => (Even::ZERO, no_slot::<C>()),
};
unsafe { slot.replace_odd_unchecked(next, link) }
}
#[inline]
pub fn detach(&mut self, key: Key<MapKeyConfig<C>>) -> Option<T> {
let slot = self.slots.as_mut_slice().get_mut(key.idx().into_usize()?)?;
slot.get_odd(key.generation())?;
decrement_len(&mut self.len);
let detached = detached_generation::<C>(key.generation());
Some(unsafe { slot.replace_odd_unchecked(detached, key.idx()) })
}
#[inline]
pub fn reattach(&mut self, key: Key<MapKeyConfig<C>>, value: T) -> Result<(), T> {
let generation = key.generation();
let Some(slot) = key
.idx()
.into_usize()
.and_then(|position| self.slots.as_mut_slice().get_mut(position))
.filter(|slot| {
slot.get_even(detached_generation::<C>(generation))
.is_some_and(|link| *link == key.idx())
})
else {
return Err(value);
};
unsafe { slot.replace_even_unchecked(generation, value) };
increment_len(&mut self.len);
Ok(())
}
pub fn clear(&mut self) {
for position in 0..self.slots.len() {
let holds_value = unsafe { self.slots.as_slice().get_unchecked(position).is_odd() };
if holds_value {
drop(unsafe { self.take(index_of::<C>(position), position) });
}
}
debug_assert!(self.is_empty());
}
#[inline]
pub fn reset(&mut self) {
self.next_free = no_slot::<C>();
self.len = Idx::<C>::ZERO;
self.slots.clear();
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(Key<MapKeyConfig<C>>, &mut T) -> bool,
{
for position in 0..self.slots.len() {
let slot = unsafe { self.slots.as_mut_slice().get_unchecked_mut(position) };
let Parity::Odd(generation, value) = slot.as_parity_mut() else {
continue;
};
let (idx, keep) = unsafe {
let idx = index_of::<C>(position);
(idx, f(slot_key::<C>(idx, generation), value))
};
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> {
let remaining = self.len();
IterMut {
slots: self.slots.as_mut_slice().iter_mut().enumerate(),
remaining,
}
}
#[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: MapConfigFor<T>> Default for GenMap<T, C> {
#[inline]
fn default() -> Self {
Self::new_with_config()
}
}
impl<T, C: MapConfigFor<T>> Index<Key<MapKeyConfig<C>>> for GenMap<T, C> {
type Output = T;
#[inline]
fn index(&self, key: Key<MapKeyConfig<C>>) -> &T {
self.get(key).expect("invalid GenMap key")
}
}
impl<T, C: MapConfigFor<T>> IndexMut<Key<MapKeyConfig<C>>> for GenMap<T, C> {
#[inline]
fn index_mut(&mut self, key: Key<MapKeyConfig<C>>) -> &mut T {
self.get_mut(key).expect("invalid GenMap key")
}
}
impl<T: fmt::Debug, C: MapConfigFor<T>> 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: MapConfigFor<T>>(slots: &mut Slots<T, C>, slot: MapSlot<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: MapConfigFor<T>>(&'a mut Slots<T, C>);
impl<T, C: MapConfigFor<T>> Drop for ClearOnUnwind<'_, T, C> {
fn drop(&mut self) {
SlotStorage::clear(self.0);
}
}
impl<T: Clone, C: MapConfigFor<T>> 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::<T, C>(&mut slots, slot.clone());
}
Self {
slots,
next_free: self.next_free,
len: self.len,
}
}
fn clone_from(&mut self, source: &Self) {
self.next_free = no_slot::<C>();
self.len = Idx::<C>::ZERO;
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::<T, C>(guard.0, slot.clone());
}
core::mem::forget(guard);
self.next_free = source.next_free;
self.len = source.len;
}
}
pub struct Iter<'a, T, C: MapConfigFor<T>> {
slots: Enumerate<core::slice::Iter<'a, MapSlot<T, C>>>,
remaining: usize,
}
impl<'a, T, C: MapConfigFor<T>> Iterator for Iter<'a, T, C> {
type Item = (Key<MapKeyConfig<C>>, &'a T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (position, slot) in self.slots.by_ref() {
if let Parity::Odd(generation, value) = slot.as_parity() {
self.remaining -= 1;
return Some((
unsafe { slot_key::<C>(index_of::<C>(position), generation) },
value,
));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, C: MapConfigFor<T>> DoubleEndedIterator for Iter<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((position, slot)) = self.slots.next_back() {
if let Parity::Odd(generation, value) = slot.as_parity() {
self.remaining -= 1;
return Some((
unsafe { slot_key::<C>(index_of::<C>(position), generation) },
value,
));
}
}
None
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for Iter<'_, T, C> {}
impl<T, C: MapConfigFor<T>> FusedIterator for Iter<'_, T, C> {}
impl<T, C: MapConfigFor<T>> Clone for Iter<'_, T, C> {
fn clone(&self) -> Self {
Self {
slots: self.slots.clone(),
remaining: self.remaining,
}
}
}
pub struct IterMut<'a, T, C: MapConfigFor<T>> {
slots: Enumerate<core::slice::IterMut<'a, MapSlot<T, C>>>,
remaining: usize,
}
impl<'a, T, C: MapConfigFor<T>> Iterator for IterMut<'a, T, C> {
type Item = (Key<MapKeyConfig<C>>, &'a mut T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (position, slot) in self.slots.by_ref() {
if let Parity::Odd(generation, value) = slot.as_parity_mut() {
self.remaining -= 1;
return Some((
unsafe { slot_key::<C>(index_of::<C>(position), generation) },
value,
));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, C: MapConfigFor<T>> DoubleEndedIterator for IterMut<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((position, slot)) = self.slots.next_back() {
if let Parity::Odd(generation, value) = slot.as_parity_mut() {
self.remaining -= 1;
return Some((
unsafe { slot_key::<C>(index_of::<C>(position), generation) },
value,
));
}
}
None
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for IterMut<'_, T, C> {}
impl<T, C: MapConfigFor<T>> FusedIterator for IterMut<'_, T, C> {}
pub struct Keys<'a, T, C: MapConfigFor<T>> {
inner: Iter<'a, T, C>,
}
impl<T, C: MapConfigFor<T>> Iterator for Keys<'_, T, C> {
type Item = Key<MapKeyConfig<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: MapConfigFor<T>> DoubleEndedIterator for Keys<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(key, _)| key)
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for Keys<'_, T, C> {}
impl<T, C: MapConfigFor<T>> FusedIterator for Keys<'_, T, C> {}
impl<T, C: MapConfigFor<T>> Clone for Keys<'_, T, C> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
pub struct Values<'a, T, C: MapConfigFor<T>> {
inner: Iter<'a, T, C>,
}
impl<'a, T, C: MapConfigFor<T>> 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: MapConfigFor<T>> DoubleEndedIterator for Values<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(_, value)| value)
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for Values<'_, T, C> {}
impl<T, C: MapConfigFor<T>> FusedIterator for Values<'_, T, C> {}
impl<T, C: MapConfigFor<T>> Clone for Values<'_, T, C> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
pub struct ValuesMut<'a, T, C: MapConfigFor<T>> {
inner: IterMut<'a, T, C>,
}
impl<'a, T, C: MapConfigFor<T>> 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: MapConfigFor<T>> DoubleEndedIterator for ValuesMut<'_, T, C> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.next_back().map(|(_, value)| value)
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for ValuesMut<'_, T, C> {}
impl<T, C: MapConfigFor<T>> FusedIterator for ValuesMut<'_, T, C> {}
pub struct IntoIter<T, C: MapConfigFor<T>>
where
Slots<T, C>: IntoIterator<Item = MapSlot<T, C>>,
{
slots: Enumerate<<Slots<T, C> as IntoIterator>::IntoIter>,
remaining: usize,
}
impl<T, C: MapConfigFor<T>> Iterator for IntoIter<T, C>
where
Slots<T, C>: IntoIterator<Item = MapSlot<T, C>>,
{
type Item = (Key<MapKeyConfig<C>>, T);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
for (position, slot) in self.slots.by_ref() {
if let Parity::Odd(generation, value) = slot.into_parity() {
self.remaining -= 1;
return Some((
unsafe { slot_key::<C>(index_of::<C>(position), generation) },
value,
));
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<T, C: MapConfigFor<T>> DoubleEndedIterator for IntoIter<T, C>
where
Slots<T, C>: IntoIterator<Item = MapSlot<T, C>>,
<Slots<T, C> as IntoIterator>::IntoIter: DoubleEndedIterator + ExactSizeIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
while let Some((position, slot)) = self.slots.next_back() {
if let Parity::Odd(generation, value) = slot.into_parity() {
self.remaining -= 1;
return Some((
unsafe { slot_key::<C>(index_of::<C>(position), generation) },
value,
));
}
}
None
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for IntoIter<T, C> where
Slots<T, C>: IntoIterator<Item = MapSlot<T, C>>
{
}
impl<T, C: MapConfigFor<T>> FusedIterator for IntoIter<T, C> where
Slots<T, C>: IntoIterator<Item = MapSlot<T, C>>
{
}
impl<T, C: MapConfigFor<T>> IntoIterator for GenMap<T, C>
where
Slots<T, C>: IntoIterator<Item = MapSlot<T, C>>,
{
type Item = (Key<MapKeyConfig<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: MapConfigFor<T>> IntoIterator for &'a GenMap<T, C> {
type Item = (Key<MapKeyConfig<C>>, &'a T);
type IntoIter = Iter<'a, T, C>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, C: MapConfigFor<T>> IntoIterator for &'a mut GenMap<T, C> {
type Item = (Key<MapKeyConfig<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: MapConfigFor<T>> {
map: &'a mut GenMap<T, C>,
position: usize,
}
impl<T, C: MapConfigFor<T>> Iterator for Drain<'_, T, C> {
type Item = (Key<MapKeyConfig<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 let Parity::Odd(generation, _) = slot.as_parity() {
unsafe {
let idx = index_of::<C>(position);
let key = slot_key::<C>(idx, generation);
return Some((key, self.map.take(idx, position)));
}
}
}
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.map.len();
(len, Some(len))
}
}
impl<T, C: MapConfigFor<T>> ExactSizeIterator for Drain<'_, T, C> {}
impl<T, C: MapConfigFor<T>> FusedIterator for Drain<'_, T, C> {}
impl<T, C: MapConfigFor<T>> Drop for Drain<'_, T, C> {
fn drop(&mut self) {
for _ in self.by_ref() {}
}
}