#[cfg(not(feature = "nightly"))]
pub(crate) use core::convert::identity as likely;
#[cfg(not(feature = "nightly"))]
pub(crate) use core::convert::identity as unlikely;
#[cfg(feature = "nightly")]
pub(crate) use core::intrinsics::{likely, unlikely};
#[cfg(feature = "nightly")]
use core::ptr::without_provenance_mut as invalid_mut;
use core::{
hash::{BuildHasher, Hash},
mem,
ptr::NonNull,
};
use crate::Equivalent;
#[cfg(not(feature = "nightly"))]
#[inline(always)]
fn invalid_mut<T>(addr: usize) -> *mut T {
addr as *mut T
}
#[inline]
pub(crate) fn equivalent_key<Q, K, V>(k: &Q) -> impl Fn(&(K, V)) -> bool + '_
where
Q: ?Sized + Equivalent<K>,
{
move |x| k.equivalent(&x.0)
}
#[cfg(not(feature = "nightly"))]
#[inline]
pub(crate) fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64
where
Q: Hash + ?Sized,
S: BuildHasher,
{
use core::hash::Hasher;
let mut state = hash_builder.build_hasher();
val.hash(&mut state);
#[allow(clippy::manual_hash_one)]
state.finish()
}
#[cfg(feature = "nightly")]
#[inline]
pub(crate) fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64
where
Q: Hash + ?Sized,
S: BuildHasher,
{
hash_builder.hash_one(val)
}
pub(crate) trait SizedTypeProperties: Sized {
const IS_ZERO_SIZED: bool = mem::size_of::<Self>() == 0;
const NEEDS_DROP: bool = mem::needs_drop::<Self>();
}
impl<T> SizedTypeProperties for T {}
pub(crate) struct InsertSlot {
pub(crate) index: usize,
}
pub(crate) struct Bucket<T> {
ptr: NonNull<T>,
}
unsafe impl<T> Send for Bucket<T> {}
impl<T> Clone for Bucket<T> {
#[inline]
fn clone(&self) -> Self {
Self { ptr: self.ptr }
}
}
impl<T> Bucket<T> {
#[inline]
pub(crate) unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self {
let ptr = if T::IS_ZERO_SIZED {
invalid_mut(index + 1)
} else {
base.as_ptr().add(index)
};
Self {
ptr: NonNull::new_unchecked(ptr),
}
}
#[inline]
pub(crate) unsafe fn to_base_index(&self, base: NonNull<T>) -> usize {
if T::IS_ZERO_SIZED {
self.ptr.as_ptr() as usize - 1
} else {
self.ptr.as_ptr().offset_from(base.as_ptr()) as usize
}
}
#[inline]
pub(crate) fn as_ptr(&self) -> *mut T {
if T::IS_ZERO_SIZED {
invalid_mut(mem::align_of::<T>())
} else {
self.ptr.as_ptr()
}
}
#[inline]
pub(crate) unsafe fn read(&self) -> T {
self.as_ptr().read()
}
#[inline]
pub(crate) unsafe fn write(&self, val: T) {
self.as_ptr().write(val);
}
#[inline]
pub(crate) unsafe fn as_ref<'a>(&self) -> &'a T {
&*self.as_ptr()
}
#[inline]
pub(crate) unsafe fn as_mut<'a>(&self) -> &'a mut T {
&mut *self.as_ptr()
}
}