From 6028aac0c745f0041c4aba46ab5e1a5c39f89e13 Mon Sep 17 00:00:00 2001 From: djugei Date: Thu, 17 Oct 2024 09:59:17 +0200 Subject: [PATCH] proof of concept --- src/map.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/src/map.rs b/src/map.rs index 1969bff54..8fed20cfb 100644 --- a/src/map.rs +++ b/src/map.rs @@ -2984,10 +2984,10 @@ where /// } /// assert!(map["b"] == 20 && map.len() == 2); /// ``` -pub struct VacantEntryRef<'a, 'b, K, Q: ?Sized, V, S, A: Allocator = Global> { +pub struct VacantEntryRef<'map, 'key, K, Q: ?Sized, V, S, A: Allocator = Global> { hash: u64, - key: &'b Q, - table: &'a mut HashMap, + key: &'key Q, + table: &'map mut HashMap, } impl Debug for VacantEntryRef<'_, '_, K, Q, V, S, A> @@ -4328,7 +4328,25 @@ impl<'a, 'b, K, Q: ?Sized, V: Default, S, A: Allocator> EntryRef<'a, 'b, K, Q, V } } -impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S, A> { +impl<'map, 'key, K, V, S, A: Allocator> VacantEntryRef<'map, 'key, K, K, V, S, A> { + /// insert, cloing the key + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert_clone(self, value: V) -> &'map mut V + where + K: Hash + Clone, + S: BuildHasher, + { + let table = &mut self.table.table; + let entry = table.insert_entry( + self.hash, + (self.key.clone(), value), + make_hasher::<_, V, S>(&self.table.hash_builder), + ); + &mut entry.1 + } +} + +impl<'map, 'key, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'map, 'key, K, Q, V, S, A> { /// Gets a reference to the key that would be used when inserting a value /// through the `VacantEntryRef`. /// @@ -4342,7 +4360,7 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S /// assert_eq!(map.entry_ref(key).key(), "poneyland"); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn key(&self) -> &'b Q { + pub fn key(&self) -> &'key Q { self.key } @@ -4364,9 +4382,9 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S /// assert_eq!(map["poneyland"], 37); /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn insert(self, value: V) -> &'a mut V + pub fn insert(self, value: V) -> &'map mut V where - K: Hash + From<&'b Q>, + K: Hash + From<&'key Q>, S: BuildHasher, { let table = &mut self.table.table; @@ -4378,6 +4396,24 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S &mut entry.1 } + /// provide explicit key at insert-time instead of relying on there being effectively a from &K to K implementation and not working with cloneable values + #[cfg_attr(feature = "inline-more", inline)] + pub fn insert_kv(self, key: K, value: V) -> &'map mut V + where + K: Hash, + for<'k> &'k K: PartialEq<&'key Q>, + S: BuildHasher, + { + let table = &mut self.table.table; + assert!(&key == self.key); + let entry = table.insert_entry( + self.hash, + (key, value), + make_hasher::<_, V, S>(&self.table.hash_builder), + ); + &mut entry.1 + } + /// Sets the value of the entry with the [`VacantEntryRef`]'s key, /// and returns an [`OccupiedEntry`]. /// @@ -4395,9 +4431,9 @@ impl<'a, 'b, K, Q: ?Sized, V, S, A: Allocator> VacantEntryRef<'a, 'b, K, Q, V, S /// } /// ``` #[cfg_attr(feature = "inline-more", inline)] - pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, S, A> + pub fn insert_entry(self, value: V) -> OccupiedEntry<'map, K, V, S, A> where - K: Hash + From<&'b Q>, + K: Hash + From<&'key Q>, S: BuildHasher, { let elem = self.table.table.insert(