Skip to content

Commit 97b4037

Browse files
committed
Use table entries (requires rust-lang#669)
1 parent c19e205 commit 97b4037

File tree

1 file changed

+63
-120
lines changed

1 file changed

+63
-120
lines changed

src/map.rs

Lines changed: 63 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::raw::{Allocator, Bucket, Global, RawExtractIf};
1+
use crate::raw::{Allocator, Global, RawExtractIf};
22
use crate::{hash_table, DefaultHashBuilder, Equivalent, HashTable, TryReserveError};
33
use core::borrow::Borrow;
44
use core::fmt::{self, Debug};
@@ -1215,18 +1215,17 @@ where
12151215
#[cfg_attr(feature = "inline-more", inline)]
12161216
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S, A> {
12171217
let hash = make_hash::<K, S>(&self.hash_builder, &key);
1218-
if let Some(elem) = self.table.raw.find(hash, equivalent_key(&key)) {
1219-
Entry::Occupied(OccupiedEntry {
1220-
hash,
1221-
elem,
1222-
table: self,
1223-
})
1224-
} else {
1225-
Entry::Vacant(VacantEntry {
1226-
hash,
1218+
let hasher = make_hasher(&self.hash_builder);
1219+
match self.table.entry(hash, equivalent_key(&key), hasher) {
1220+
hash_table::Entry::Occupied(inner) => Entry::Occupied(OccupiedEntry {
1221+
inner,
1222+
marker: PhantomData,
1223+
}),
1224+
hash_table::Entry::Vacant(inner) => Entry::Vacant(VacantEntry {
1225+
inner,
12271226
key,
1228-
table: self,
1229-
})
1227+
marker: PhantomData,
1228+
}),
12301229
}
12311230
}
12321231

@@ -1253,18 +1252,17 @@ where
12531252
Q: Hash + Equivalent<K> + ?Sized,
12541253
{
12551254
let hash = make_hash::<Q, S>(&self.hash_builder, key);
1256-
if let Some(elem) = self.table.raw.find(hash, equivalent_key(key)) {
1257-
EntryRef::Occupied(OccupiedEntry {
1258-
hash,
1259-
elem,
1260-
table: self,
1261-
})
1262-
} else {
1263-
EntryRef::Vacant(VacantEntryRef {
1264-
hash,
1255+
let hasher = make_hasher(&self.hash_builder);
1256+
match self.table.entry(hash, equivalent_key(key), hasher) {
1257+
hash_table::Entry::Occupied(inner) => EntryRef::Occupied(OccupiedEntry {
1258+
inner,
1259+
marker: PhantomData,
1260+
}),
1261+
hash_table::Entry::Vacant(inner) => EntryRef::Vacant(VacantEntryRef {
1262+
inner,
12651263
key,
1266-
table: self,
1267-
})
1264+
marker: PhantomData,
1265+
}),
12681266
}
12691267
}
12701268

@@ -1827,33 +1825,15 @@ where
18271825
#[cfg_attr(feature = "inline-more", inline)]
18281826
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
18291827
let hash = make_hash::<K, S>(&self.hash_builder, &k);
1830-
match self.find_or_find_insert_index(hash, &k) {
1831-
Ok(bucket) => Some(mem::replace(unsafe { &mut bucket.as_mut().1 }, v)),
1832-
Err(index) => {
1833-
unsafe {
1834-
self.table.raw.insert_at_index(hash, index, (k, v));
1835-
}
1828+
match self.entry(k) {
1829+
Entry::Occupied(mut entry) => Some(entry.insert(v)),
1830+
Entry::Vacant(entry) => {
1831+
entry.insert(v);
18361832
None
18371833
}
18381834
}
18391835
}
18401836

1841-
#[cfg_attr(feature = "inline-more", inline)]
1842-
pub(crate) fn find_or_find_insert_index<Q>(
1843-
&mut self,
1844-
hash: u64,
1845-
key: &Q,
1846-
) -> Result<Bucket<(K, V)>, usize>
1847-
where
1848-
Q: Equivalent<K> + ?Sized,
1849-
{
1850-
self.table.raw.find_or_find_insert_index(
1851-
hash,
1852-
equivalent_key(key),
1853-
make_hasher(&self.hash_builder),
1854-
)
1855-
}
1856-
18571837
/// Insert a key-value pair into the map without checking
18581838
/// if the key already exists in the map.
18591839
///
@@ -1914,11 +1894,10 @@ where
19141894
#[cfg_attr(feature = "inline-more", inline)]
19151895
pub unsafe fn insert_unique_unchecked(&mut self, k: K, v: V) -> (&K, &mut V) {
19161896
let hash = make_hash::<K, S>(&self.hash_builder, &k);
1917-
let bucket =
1897+
let entry =
19181898
self.table
1919-
.raw
1920-
.insert(hash, (k, v), make_hasher::<_, V, S>(&self.hash_builder));
1921-
let (k_ref, v_ref) = unsafe { bucket.as_mut() };
1899+
.insert_unique(hash, (k, v), make_hasher::<_, V, S>(&self.hash_builder));
1900+
let (k_ref, v_ref) = entry.into_mut();
19221901
(k_ref, v_ref)
19231902
}
19241903

@@ -2034,7 +2013,7 @@ where
20342013
Q: Hash + Equivalent<K> + ?Sized,
20352014
{
20362015
let hash = make_hash::<Q, S>(&self.hash_builder, k);
2037-
self.table.raw.remove_entry(hash, equivalent_key(k))
2016+
self.table.remove_entry(hash, equivalent_key(k))
20382017
}
20392018

20402019
/// Returns the total amount of memory allocated internally by the hash
@@ -2812,9 +2791,8 @@ impl<K: Debug, V: Debug, S, A: Allocator> Debug for Entry<'_, K, V, S, A> {
28122791
/// assert_eq!(map.len(), 2);
28132792
/// ```
28142793
pub struct OccupiedEntry<'a, K, V, S = DefaultHashBuilder, A: Allocator = Global> {
2815-
hash: u64,
2816-
elem: Bucket<(K, V)>,
2817-
table: &'a mut HashMap<K, V, S, A>,
2794+
inner: hash_table::OccupiedEntry<'a, (K, V), A>,
2795+
marker: PhantomData<&'a mut S>,
28182796
}
28192797

28202798
unsafe impl<K, V, S, A> Send for OccupiedEntry<'_, K, V, S, A>
@@ -2874,9 +2852,9 @@ impl<K: Debug, V: Debug, S, A: Allocator> Debug for OccupiedEntry<'_, K, V, S, A
28742852
/// assert!(map[&"b"] == 20 && map.len() == 2);
28752853
/// ```
28762854
pub struct VacantEntry<'a, K, V, S = DefaultHashBuilder, A: Allocator = Global> {
2877-
hash: u64,
2855+
inner: hash_table::VacantEntry<'a, (K, V), A>,
28782856
key: K,
2879-
table: &'a mut HashMap<K, V, S, A>,
2857+
marker: PhantomData<&'a mut S>,
28802858
}
28812859

28822860
impl<K: Debug, V, S, A: Allocator> Debug for VacantEntry<'_, K, V, S, A> {
@@ -3018,9 +2996,9 @@ where
30182996
/// assert!(map["b"] == 20 && map.len() == 2);
30192997
/// ```
30202998
pub struct VacantEntryRef<'map, 'key, K, Q: ?Sized, V, S, A: Allocator = Global> {
3021-
hash: u64,
2999+
inner: hash_table::VacantEntry<'map, (K, V), A>,
30223000
key: &'key Q,
3023-
table: &'map mut HashMap<K, V, S, A>,
3001+
marker: PhantomData<&'map mut S>,
30243002
}
30253003

30263004
impl<K, Q, V, S, A> Debug for VacantEntryRef<'_, '_, K, Q, V, S, A>
@@ -3817,7 +3795,7 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
38173795
/// ```
38183796
#[cfg_attr(feature = "inline-more", inline)]
38193797
pub fn key(&self) -> &K {
3820-
unsafe { &self.elem.as_ref().0 }
3798+
&self.inner.get().0
38213799
}
38223800

38233801
/// Take the ownership of the key and value from the map.
@@ -3846,7 +3824,7 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
38463824
/// ```
38473825
#[cfg_attr(feature = "inline-more", inline)]
38483826
pub fn remove_entry(self) -> (K, V) {
3849-
unsafe { self.table.table.raw.remove(self.elem).0 }
3827+
self.inner.remove().0
38503828
}
38513829

38523830
/// Gets a reference to the value in the entry.
@@ -3867,7 +3845,7 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
38673845
/// ```
38683846
#[cfg_attr(feature = "inline-more", inline)]
38693847
pub fn get(&self) -> &V {
3870-
unsafe { &self.elem.as_ref().1 }
3848+
&self.inner.get().1
38713849
}
38723850

38733851
/// Gets a mutable reference to the value in the entry.
@@ -3899,7 +3877,7 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
38993877
/// ```
39003878
#[cfg_attr(feature = "inline-more", inline)]
39013879
pub fn get_mut(&mut self) -> &mut V {
3902-
unsafe { &mut self.elem.as_mut().1 }
3880+
&mut self.inner.get_mut().1
39033881
}
39043882

39053883
/// Converts the `OccupiedEntry` into a mutable reference to the value in the entry
@@ -3930,7 +3908,7 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
39303908
/// ```
39313909
#[cfg_attr(feature = "inline-more", inline)]
39323910
pub fn into_mut(self) -> &'a mut V {
3933-
unsafe { &mut self.elem.as_mut().1 }
3911+
&mut self.inner.into_mut().1
39343912
}
39353913

39363914
/// Sets the value of the entry, and returns the entry's old value.
@@ -4036,30 +4014,25 @@ impl<'a, K, V, S, A: Allocator> OccupiedEntry<'a, K, V, S, A> {
40364014
where
40374015
F: FnOnce(&K, V) -> Option<V>,
40384016
{
4039-
unsafe {
4040-
let mut spare_key = None;
4017+
let mut spare_key = None;
40414018

4042-
self.table
4043-
.table
4044-
.raw
4045-
.replace_bucket_with(self.elem.clone(), |(key, value)| {
4046-
if let Some(new_value) = f(&key, value) {
4047-
Some((key, new_value))
4048-
} else {
4049-
spare_key = Some(key);
4050-
None
4051-
}
4052-
});
4053-
4054-
if let Some(key) = spare_key {
4055-
Entry::Vacant(VacantEntry {
4056-
hash: self.hash,
4057-
key,
4058-
table: self.table,
4059-
})
4019+
match self.inner.replace_entry_with(|(key, value)| {
4020+
if let Some(new_value) = f(&key, value) {
4021+
Some((key, new_value))
40604022
} else {
4061-
Entry::Occupied(self)
4023+
spare_key = Some(key);
4024+
None
40624025
}
4026+
}) {
4027+
hash_table::Entry::Vacant(inner) => Entry::Vacant(VacantEntry {
4028+
inner,
4029+
key: unsafe { spare_key.unwrap_unchecked() },
4030+
marker: PhantomData,
4031+
}),
4032+
hash_table::Entry::Occupied(inner) => Entry::Occupied(OccupiedEntry {
4033+
inner,
4034+
marker: PhantomData,
4035+
}),
40634036
}
40644037
}
40654038
}
@@ -4122,13 +4095,7 @@ impl<'a, K, V, S, A: Allocator> VacantEntry<'a, K, V, S, A> {
41224095
K: Hash,
41234096
S: BuildHasher,
41244097
{
4125-
let table = &mut self.table.table.raw;
4126-
let entry = table.insert_entry(
4127-
self.hash,
4128-
(self.key, value),
4129-
make_hasher::<_, V, S>(&self.table.hash_builder),
4130-
);
4131-
&mut entry.1
4098+
&mut self.inner.insert((self.key, value)).into_mut().1
41324099
}
41334100

41344101
/// Sets the value of the entry with the [`VacantEntry`]'s key,
@@ -4153,15 +4120,9 @@ impl<'a, K, V, S, A: Allocator> VacantEntry<'a, K, V, S, A> {
41534120
K: Hash,
41544121
S: BuildHasher,
41554122
{
4156-
let elem = self.table.table.raw.insert(
4157-
self.hash,
4158-
(self.key, value),
4159-
make_hasher::<_, V, S>(&self.table.hash_builder),
4160-
);
41614123
OccupiedEntry {
4162-
hash: self.hash,
4163-
elem,
4164-
table: self.table,
4124+
inner: self.inner.insert((self.key, value)),
4125+
marker: PhantomData,
41654126
}
41664127
}
41674128
}
@@ -4461,13 +4422,7 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
44614422
&'key Q: Into<K>,
44624423
S: BuildHasher,
44634424
{
4464-
let table = &mut self.table.table.raw;
4465-
let entry = table.insert_entry(
4466-
self.hash,
4467-
(self.key.into(), value),
4468-
make_hasher::<_, V, S>(&self.table.hash_builder),
4469-
);
4470-
&mut entry.1
4425+
&mut self.inner.insert((self.key.into(), value)).into_mut().1
44714426
}
44724427

44734428
/// Sets the key and value of the entry and returns a mutable reference to
@@ -4506,17 +4461,11 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
45064461
Q: Equivalent<K>,
45074462
S: BuildHasher,
45084463
{
4509-
let table = &mut self.table.table.raw;
45104464
assert!(
45114465
(self.key).equivalent(&key),
45124466
"key used for Entry creation is not equivalent to the one used for insertion"
45134467
);
4514-
let entry = table.insert_entry(
4515-
self.hash,
4516-
(key, value),
4517-
make_hasher::<_, V, S>(&self.table.hash_builder),
4518-
);
4519-
&mut entry.1
4468+
&mut self.inner.insert((key, value)).into_mut().1
45204469
}
45214470

45224471
/// Sets the value of the entry with the [`VacantEntryRef`]'s key,
@@ -4542,15 +4491,9 @@ impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K,
45424491
&'key Q: Into<K>,
45434492
S: BuildHasher,
45444493
{
4545-
let elem = self.table.table.raw.insert(
4546-
self.hash,
4547-
(self.key.into(), value),
4548-
make_hasher::<_, V, S>(&self.table.hash_builder),
4549-
);
45504494
OccupiedEntry {
4551-
hash: self.hash,
4552-
elem,
4553-
table: self.table,
4495+
inner: self.inner.insert((self.key.into(), value)),
4496+
marker: PhantomData,
45544497
}
45554498
}
45564499
}

0 commit comments

Comments
 (0)