Skip to content

Commit b31e883

Browse files
committed
Add HashTable::get_many_mut
1 parent 7561137 commit b31e883

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

src/table.rs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,137 @@ where
863863
},
864864
}
865865
}
866+
867+
/// Attempts to get mutable references to `N` values in the map at once.
868+
///
869+
/// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
870+
/// the `i`th key to be looked up.
871+
///
872+
/// Returns an array of length `N` with the results of each query. For soundness, at most one
873+
/// mutable reference will be returned to any value. `None` will be returned if any of the
874+
/// keys are duplicates or missing.
875+
///
876+
/// # Examples
877+
///
878+
/// ```
879+
/// # #[cfg(feature = "nightly")]
880+
/// # fn test() {
881+
/// use ahash::AHasher;
882+
/// use hashbrown::hash_table::Entry;
883+
/// use hashbrown::HashTable;
884+
/// use std::hash::{BuildHasher, BuildHasherDefault};
885+
///
886+
/// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
887+
/// let hasher = BuildHasherDefault::<AHasher>::default();
888+
/// let hasher = |val: &_| hasher.hash_one(val);
889+
/// for (k, v) in [
890+
/// ("Bodleian Library", 1602),
891+
/// ("Athenæum", 1807),
892+
/// ("Herzogin-Anna-Amalia-Bibliothek", 1691),
893+
/// ("Library of Congress", 1800),
894+
/// ] {
895+
/// libraries.insert_unchecked(hasher(&k), (k, v), |(k, _)| hasher(&k));
896+
/// }
897+
///
898+
/// let keys = ["Athenæum", "Library of Congress"];
899+
/// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
900+
/// assert_eq!(
901+
/// got,
902+
/// Some([&mut ("Athenæum", 1807), &mut ("Library of Congress", 1800),]),
903+
/// );
904+
///
905+
/// // Missing keys result in None
906+
/// let keys = ["Athenæum", "New York Public Library"];
907+
/// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
908+
/// assert_eq!(got, None);
909+
///
910+
/// // Duplicate keys result in None
911+
/// let keys = ["Athenæum", "Athenæum"];
912+
/// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
913+
/// assert_eq!(got, None);
914+
/// # }
915+
/// # fn main() {
916+
/// # #[cfg(feature = "nightly")]
917+
/// # test()
918+
/// # }
919+
/// ```
920+
pub fn get_many_mut<const N: usize>(
921+
&mut self,
922+
hashes: [u64; N],
923+
eq: impl FnMut(usize, &T) -> bool,
924+
) -> Option<[&'_ mut T; N]> {
925+
self.table.get_many_mut(hashes, eq)
926+
}
927+
928+
/// Attempts to get mutable references to `N` values in the map at once, without validating that
929+
/// the values are unique.
930+
///
931+
/// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
932+
/// the `i`th key to be looked up.
933+
///
934+
/// Returns an array of length `N` with the results of each query. `None` will be returned if
935+
/// any of the keys are missing.
936+
///
937+
/// For a safe alternative see [`get_many_mut`](`HashMap::get_many_mut`).
938+
///
939+
/// # Safety
940+
///
941+
/// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
942+
/// references are not used.
943+
///
944+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
945+
///
946+
/// # Examples
947+
///
948+
/// ```
949+
/// # #[cfg(feature = "nightly")]
950+
/// # fn test() {
951+
/// use ahash::AHasher;
952+
/// use hashbrown::hash_table::Entry;
953+
/// use hashbrown::HashTable;
954+
/// use std::hash::{BuildHasher, BuildHasherDefault};
955+
///
956+
/// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
957+
/// let hasher = BuildHasherDefault::<AHasher>::default();
958+
/// let hasher = |val: &_| hasher.hash_one(val);
959+
/// for (k, v) in [
960+
/// ("Bodleian Library", 1602),
961+
/// ("Athenæum", 1807),
962+
/// ("Herzogin-Anna-Amalia-Bibliothek", 1691),
963+
/// ("Library of Congress", 1800),
964+
/// ] {
965+
/// libraries.insert_unchecked(hasher(&k), (k, v), |(k, _)| hasher(&k));
966+
/// }
967+
///
968+
/// let keys = ["Athenæum", "Library of Congress"];
969+
/// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
970+
/// assert_eq!(
971+
/// got,
972+
/// Some([&mut ("Athenæum", 1807), &mut ("Library of Congress", 1800),]),
973+
/// );
974+
///
975+
/// // Missing keys result in None
976+
/// let keys = ["Athenæum", "New York Public Library"];
977+
/// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
978+
/// assert_eq!(got, None);
979+
///
980+
/// // Duplicate keys result in None
981+
/// let keys = ["Athenæum", "Athenæum"];
982+
/// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
983+
/// assert_eq!(got, None);
984+
/// # }
985+
/// # fn main() {
986+
/// # #[cfg(feature = "nightly")]
987+
/// # test()
988+
/// # }
989+
/// ```
990+
pub unsafe fn get_many_unchecked_mut<const N: usize>(
991+
&mut self,
992+
hashes: [u64; N],
993+
eq: impl FnMut(usize, &T) -> bool,
994+
) -> Option<[&'_ mut T; N]> {
995+
self.table.get_many_unchecked_mut(hashes, eq)
996+
}
866997
}
867998

868999
impl<T, A> IntoIterator for HashTable<T, A>

0 commit comments

Comments
 (0)