#[cfg(test)]
mod tests;
use {
crate::{
linear_storage::LinearStorage,
pos_vec::pos::{InUse, Pos},
},
core::{
borrow::Borrow,
fmt::{Debug, Formatter},
hash::{BuildHasher, Hash},
mem::{self},
},
hashbrown::hash_map,
};
pub enum Entry<'a, K, V, S> {
Occupied(OccupiedEntry<'a, K, V, S>),
Vacant(VacantEntry<'a, K, V, S>),
}
pub enum EntryRef<'a, 'b, K, Q: ?Sized, V, S> {
Occupied(OccupiedEntry<'a, K, V, S>),
Vacant(VacantEntryRef<'a, 'b, K, Q, V, S>),
}
pub struct OccupiedEntry<'a, K, V, S> {
pub(crate) entry: hash_map::OccupiedEntry<'a, K, Pos<InUse>, S>,
pub(crate) entries: &'a mut LinearStorage<V>,
}
pub struct VacantEntry<'a, K, V, S> {
pub(crate) entry: hash_map::VacantEntry<'a, K, Pos<InUse>, S>,
pub(crate) entries: &'a mut LinearStorage<V>,
}
pub struct VacantEntryRef<'a, 'b, K, Q, V, S>
where
Q: ?Sized,
{
pub(crate) entry: hash_map::VacantEntryRef<'a, 'b, K, Q, Pos<InUse>, S>,
pub(crate) entries: &'a mut LinearStorage<V>,
}
impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn get(&self) -> &V {
unsafe {
self.entries.get_unchecked(self.entry.get())
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn get_mut(&mut self) -> &mut V {
unsafe {
self.entries.get_unchecked_mut(self.entry.get())
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(&mut self, value: V) -> V {
mem::replace(self.get_mut(), value)
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn into_mut(self) -> &'a mut V {
unsafe {
self.entries.get_unchecked_mut(self.entry.get())
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn key(&self) -> &K {
self.entry.key()
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove(self) -> V {
let pos = self.entry.remove();
unsafe {
self.entries.take_unchecked(pos)
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn remove_entry(self) -> (K, V) {
let (k, pos) = self.entry.remove_entry();
let value = unsafe {
self.entries.take_unchecked(pos)
};
(k, value)
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn replace_entry_with<F>(self, f: F) -> Entry<'a, K, V, S>
where
F: FnOnce(&K, V) -> Option<V>,
{
let entry = self.entry.replace_entry_with(|k, pos| {
let v = unsafe { self.entries.take_unchecked(pos) };
match f(k, v) {
None => None,
Some(v) => Some(self.entries.insert(v)),
}
});
match entry {
hash_map::Entry::Occupied(o) => Entry::Occupied(OccupiedEntry {
entry: o,
entries: self.entries,
}),
hash_map::Entry::Vacant(v) => Entry::Vacant(VacantEntry {
entry: v,
entries: self.entries,
}),
}
}
}
impl<'a, K, V, S> VacantEntry<'a, K, V, S> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(self, value: V) -> &'a mut V
where
K: Hash,
S: BuildHasher,
{
let pos = self.entries.insert(value);
let pos = self.entry.insert(pos);
unsafe { self.entries.get_unchecked_mut(pos) }
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S>
where
K: Hash,
S: BuildHasher,
{
let pos = self.entries.insert(value);
let entry = self.entry.insert_entry(pos);
OccupiedEntry {
entry,
entries: self.entries,
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn into_key(self) -> K {
self.entry.into_key()
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn key(&self) -> &K {
self.entry.key()
}
}
impl<'a, K, V, S> Entry<'a, K, V, S> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn and_modify<F>(mut self, f: F) -> Self
where
F: FnOnce(&mut V),
{
if let Entry::Occupied(e) = &mut self {
f(e.get_mut());
}
self
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn and_replace_entry_with<F>(self, f: F) -> Self
where
F: FnOnce(&K, V) -> Option<V>,
{
match self {
Entry::Occupied(o) => o.replace_entry_with(f),
Entry::Vacant(v) => Entry::Vacant(v),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S>
where
K: Hash,
S: BuildHasher,
{
match self {
Entry::Occupied(mut o) => {
o.insert(value);
o
}
Entry::Vacant(v) => v.insert_entry(value),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn key(&self) -> &K {
match self {
Entry::Occupied(e) => e.key(),
Entry::Vacant(e) => e.key(),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_default(self) -> &'a mut V
where
K: Hash,
S: BuildHasher,
V: Default,
{
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(V::default()),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_insert(self, value: V) -> &'a mut V
where
K: Hash,
S: BuildHasher,
{
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(value),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_insert_with<F>(self, f: F) -> &'a mut V
where
K: Hash,
S: BuildHasher,
F: FnOnce() -> V,
{
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => v.insert(f()),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_insert_with_key<F>(self, f: F) -> &'a mut V
where
K: Hash,
S: BuildHasher,
F: FnOnce(&K) -> V,
{
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(v) => {
let value = f(v.key());
v.insert(value)
}
}
}
}
impl<'a, 'b, K, Q, V, S> VacantEntryRef<'a, 'b, K, Q, V, S>
where
Q: ?Sized,
{
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(self, value: V) -> &'a mut V
where
K: Hash + From<&'b Q>,
S: BuildHasher,
{
let pos = self.entries.insert(value);
let pos = self.entry.insert(pos);
unsafe { self.entries.get_unchecked_mut(pos) }
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S>
where
K: Hash + From<&'b Q>,
S: BuildHasher,
{
let pos = self.entries.insert(value);
let entry = self.entry.insert_entry(pos);
OccupiedEntry {
entry,
entries: self.entries,
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn key(&self) -> &'b Q {
self.entry.key()
}
}
impl<'a, 'b, K, Q, V, S> EntryRef<'a, 'b, K, Q, V, S>
where
Q: ?Sized,
{
#[cfg_attr(feature = "inline-more", inline)]
pub fn and_modify<F>(mut self, f: F) -> Self
where
F: FnOnce(&mut V),
{
if let EntryRef::Occupied(e) = &mut self {
f(e.get_mut());
}
self
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V, S>
where
K: Hash + From<&'b Q>,
S: BuildHasher,
{
match self {
EntryRef::Occupied(mut o) => {
o.insert(value);
o
}
EntryRef::Vacant(v) => v.insert_entry(value),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn key(&self) -> &Q
where
K: Borrow<Q>,
{
match self {
EntryRef::Occupied(e) => e.key().borrow(),
EntryRef::Vacant(e) => e.key(),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_default(self) -> &'a mut V
where
K: Hash + From<&'b Q>,
S: BuildHasher,
V: Default,
{
match self {
EntryRef::Occupied(o) => o.into_mut(),
EntryRef::Vacant(v) => v.insert(V::default()),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_insert(self, value: V) -> &'a mut V
where
K: Hash + From<&'b Q>,
S: BuildHasher,
{
match self {
EntryRef::Occupied(o) => o.into_mut(),
EntryRef::Vacant(v) => v.insert(value),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_insert_with<F>(self, f: F) -> &'a mut V
where
K: Hash + From<&'b Q>,
S: BuildHasher,
F: FnOnce() -> V,
{
match self {
EntryRef::Occupied(o) => o.into_mut(),
EntryRef::Vacant(v) => v.insert(f()),
}
}
#[cfg_attr(feature = "inline-more", inline)]
pub fn or_insert_with_key<F>(self, f: F) -> &'a mut V
where
K: Hash + From<&'b Q>,
S: BuildHasher,
F: FnOnce(&'b Q) -> V,
{
match self {
EntryRef::Occupied(o) => o.into_mut(),
EntryRef::Vacant(v) => {
let value = f(v.key());
v.insert(value)
}
}
}
}
impl<K, V, S> Debug for OccupiedEntry<'_, K, V, S>
where
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
.field("value", self.get())
.finish()
}
}
impl<K, V, S> Debug for VacantEntry<'_, K, V, S>
where
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("VacantEntry").field(self.key()).finish()
}
}
impl<K, Q, V, S> Debug for VacantEntryRef<'_, '_, K, Q, V, S>
where
Q: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("VacantEntryRef").field(self.key()).finish()
}
}
impl<K, V, S> Debug for Entry<'_, K, V, S>
where
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match *self {
Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
}
}
}
impl<K, Q, V, S> Debug for EntryRef<'_, '_, K, Q, V, S>
where
Q: Debug,
K: Debug,
V: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match *self {
EntryRef::Vacant(ref v) => f.debug_tuple("EntryRef").field(v).finish(),
EntryRef::Occupied(ref o) => f.debug_tuple("EntryRef").field(o).finish(),
}
}
}
unsafe impl<K, V, S> Send for OccupiedEntry<'_, K, V, S>
where
K: Send,
V: Send,
S: Send,
{
}
unsafe impl<K, V, S> Sync for OccupiedEntry<'_, K, V, S>
where
K: Sync,
V: Sync,
S: Sync,
{
}
unsafe impl<K, V, S> Send for VacantEntry<'_, K, V, S>
where
K: Send,
V: Send,
S: Send,
{
}
unsafe impl<K, V, S> Sync for VacantEntry<'_, K, V, S>
where
K: Sync,
V: Sync,
S: Sync,
{
}
unsafe impl<K, Q, V, S> Send for VacantEntryRef<'_, '_, K, Q, V, S>
where
Q: Send,
K: Send,
V: Send,
S: Send,
{
}
unsafe impl<K, Q, V, S> Sync for VacantEntryRef<'_, '_, K, Q, V, S>
where
Q: Sync,
K: Sync,
V: Sync,
S: Sync,
{
}