#![allow(unsafe_code)]
use super::{equivalent, Entry, HashValue, IndexMapCore, VacantEntry};
use core::fmt;
use core::mem::replace;
use hashbrown::raw::RawTable;
type RawBucket = hashbrown::raw::Bucket<usize>;
pub(super) struct DebugIndices<'a>(pub &'a RawTable<usize>);
impl fmt::Debug for DebugIndices<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let indices = unsafe { self.0.iter().map(|raw_bucket| raw_bucket.read()) };
f.debug_list().entries(indices).finish()
}
}
impl<K, V> IndexMapCore<K, V> {
pub(super) fn erase_indices_sweep(&mut self, start: usize, end: usize) {
unsafe {
let offset = end - start;
for bucket in self.indices.iter() {
let i = bucket.read();
if i >= end {
bucket.write(i - offset);
} else if i >= start {
self.indices.erase(bucket);
}
}
}
}
pub(crate) fn entry(&mut self, hash: HashValue, key: K) -> Entry<'_, K, V>
where
K: Eq,
{
let eq = equivalent(&key, &self.entries);
match self.indices.find(hash.get(), eq) {
Some(raw_bucket) => Entry::Occupied(OccupiedEntry {
map: self,
raw_bucket,
key,
}),
None => Entry::Vacant(VacantEntry {
map: self,
hash,
key,
}),
}
}
pub(super) fn indices_mut(&mut self) -> impl Iterator<Item = &mut usize> {
unsafe { self.indices.iter().map(|bucket| bucket.as_mut()) }
}
fn find_index(&self, index: usize) -> RawBucket {
let hash = self.entries[index].hash.get();
self.indices
.find(hash, move |&i| i == index)
.expect("index not found")
}
pub(crate) fn swap_indices(&mut self, a: usize, b: usize) {
unsafe {
let raw_bucket_a = self.find_index(a);
let raw_bucket_b = self.find_index(b);
raw_bucket_a.write(b);
raw_bucket_b.write(a);
}
self.entries.swap(a, b);
}
}
pub struct OccupiedEntry<'a, K, V> {
map: &'a mut IndexMapCore<K, V>,
raw_bucket: RawBucket,
key: K,
}
unsafe impl<K: Sync, V: Sync> Sync for OccupiedEntry<'_, K, V> {}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
pub fn key(&self) -> &K {
&self.map.entries[self.index()].key
}
pub fn get(&self) -> &V {
&self.map.entries[self.index()].value
}
pub fn get_mut(&mut self) -> &mut V {
let index = self.index();
&mut self.map.entries[index].value
}
pub(crate) fn replace_key(self) -> K {
let index = self.index();
let old_key = &mut self.map.entries[index].key;
replace(old_key, self.key)
}
#[inline]
pub fn index(&self) -> usize {
unsafe { self.raw_bucket.read() }
}
pub fn into_mut(self) -> &'a mut V {
let index = self.index();
&mut self.map.entries[index].value
}
pub fn swap_remove_entry(self) -> (K, V) {
let index = unsafe { self.map.indices.remove(self.raw_bucket) };
self.map.swap_remove_finish(index)
}
pub fn shift_remove_entry(self) -> (K, V) {
let index = unsafe { self.map.indices.remove(self.raw_bucket) };
self.map.shift_remove_finish(index)
}
}