From a4c6661836c19572eff96dcee580c8c036810f3c Mon Sep 17 00:00:00 2001 From: Mark Tyrkba Date: Wed, 29 Jan 2025 22:43:58 +0300 Subject: [PATCH 1/5] `new` and `with_capacity` functions --- lib.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/lib.rs b/lib.rs index 1abff27..db60ae3 100644 --- a/lib.rs +++ b/lib.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(missing_docs)] - //! # Fx Hash //! //! This hashing algorithm was extracted from the Rustc compiler. This is the same hashing @@ -28,7 +26,7 @@ use std::collections::{HashMap, HashSet}; use std::default::Default; use std::hash::{BuildHasherDefault, Hash, Hasher}; -use std::ops::BitXor; +use std::ops::{BitXor, Deref}; extern crate byteorder; use byteorder::{ByteOrder, NativeEndian}; @@ -38,15 +36,54 @@ pub type FxBuildHasher = BuildHasherDefault; /// A `HashMap` using a default Fx hasher. /// -/// Use `FxHashMap::default()`, not `new()` to create a new `FxHashMap`. -/// To create with a reserved capacity, use `FxHashMap::with_capacity_and_hasher(num, Default::default())`. -pub type FxHashMap = HashMap; +#[repr(transparent)] +pub struct FxHashMap(HashMap); + +impl FxHashMap { + #[inline] + pub fn new() -> Self { + Self(HashMap::with_hasher(FxBuildHasher::default())) + } + + #[inline] + pub fn with_capacity(n: usize) -> Self { + Self(HashMap::with_capacity_and_hasher(n, FxBuildHasher::default())) + } +} + +impl Deref for FxHashMap { + type Target = HashMap; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} /// A `HashSet` using a default Fx hasher. -/// -/// Note: Use `FxHashSet::default()`, not `new()` to create a new `FxHashSet`. -/// To create with a reserved capacity, use `FxHashSet::with_capacity_and_hasher(num, Default::default())`. -pub type FxHashSet = HashSet; +#[repr(transparent)] +pub struct FxHashSet(HashSet); + +impl FxHashSet { + #[inline] + pub fn new() -> Self { + Self(HashSet::with_hasher(FxBuildHasher::default())) + } + + #[inline] + pub fn with_capacity(n: usize) -> Self { + Self(HashSet::with_capacity_and_hasher(n, FxBuildHasher::default())) + } +} + +impl Deref for FxHashSet { + type Target = HashSet; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} const ROTATE: u32 = 5; const SEED64: u64 = 0x51_7c_c1_b7_27_22_0a_95; @@ -58,7 +95,7 @@ const SEED: usize = SEED32 as usize; const SEED: usize = SEED64 as usize; trait HashWord { - fn hash_word(&mut self, Self); + fn hash_word(&mut self, _: Self); } macro_rules! impl_hash_word { From 6824efe1fe810c5c2abda11d045944121983dd89 Mon Sep 17 00:00:00 2001 From: Mark Tyrkba Date: Wed, 29 Jan 2025 22:46:11 +0300 Subject: [PATCH 2/5] Derive `Default` to not introduce breaking changes --- lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib.rs b/lib.rs index db60ae3..cdb3141 100644 --- a/lib.rs +++ b/lib.rs @@ -36,6 +36,7 @@ pub type FxBuildHasher = BuildHasherDefault; /// A `HashMap` using a default Fx hasher. /// +#[derive(Default)] #[repr(transparent)] pub struct FxHashMap(HashMap); @@ -61,6 +62,7 @@ impl Deref for FxHashMap { } /// A `HashSet` using a default Fx hasher. +#[derive(Default)] #[repr(transparent)] pub struct FxHashSet(HashSet); From f3e961a51c547cd6a7f70633e61fd57353d92ba3 Mon Sep 17 00:00:00 2001 From: Mark Tyrkba Date: Wed, 29 Jan 2025 22:48:33 +0300 Subject: [PATCH 3/5] Oops, forgot to implement `DerefMut` --- lib.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib.rs b/lib.rs index cdb3141..ad97312 100644 --- a/lib.rs +++ b/lib.rs @@ -26,7 +26,7 @@ use std::collections::{HashMap, HashSet}; use std::default::Default; use std::hash::{BuildHasherDefault, Hash, Hasher}; -use std::ops::{BitXor, Deref}; +use std::ops::{BitXor, Deref, DerefMut}; extern crate byteorder; use byteorder::{ByteOrder, NativeEndian}; @@ -61,6 +61,13 @@ impl Deref for FxHashMap { } } +impl DerefMut for FxHashMap { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + /// A `HashSet` using a default Fx hasher. #[derive(Default)] #[repr(transparent)] @@ -78,6 +85,13 @@ impl FxHashSet { } } +impl DerefMut for FxHashSet { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + impl Deref for FxHashSet { type Target = HashSet; From b4b546127e7df8c2e1e9d3c7f9019fcbf8d6770d Mon Sep 17 00:00:00 2001 From: Mark Tyrkba Date: Wed, 29 Jan 2025 22:54:20 +0300 Subject: [PATCH 4/5] Implement `FromIterator` --- lib.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib.rs b/lib.rs index ad97312..62a92d1 100644 --- a/lib.rs +++ b/lib.rs @@ -23,6 +23,7 @@ //! potentially cause quadratic behavior in `HashMap`s. So it is not recommended to expose //! this hash in places where collissions or DDOS attacks may be a concern. +use std::iter::FromIterator; use std::collections::{HashMap, HashSet}; use std::default::Default; use std::hash::{BuildHasherDefault, Hash, Hasher}; @@ -68,6 +69,20 @@ impl DerefMut for FxHashMap { } } +impl FromIterator<(K, V)> for FxHashMap +where + K: Eq + Hash +{ + #[inline] + fn from_iter(iter: I) -> Self + where + I: IntoIterator + { + let inner_set = HashMap::::from_iter(iter); + Self(inner_set) + } +} + /// A `HashSet` using a default Fx hasher. #[derive(Default)] #[repr(transparent)] @@ -101,6 +116,20 @@ impl Deref for FxHashSet { } } +impl FromIterator for FxHashSet +where + V: Eq + Hash +{ + #[inline] + fn from_iter(iter: I) -> Self + where + I: IntoIterator + { + let inner_set = HashSet::::from_iter(iter); + Self(inner_set) + } +} + const ROTATE: u32 = 5; const SEED64: u64 = 0x51_7c_c1_b7_27_22_0a_95; const SEED32: u32 = 0x9e_37_79_b9; From 2b6155176a1a2ef412a1ed33d09fbbd925daebbd Mon Sep 17 00:00:00 2001 From: Mark Tyrkba Date: Thu, 30 Jan 2025 12:18:53 +0300 Subject: [PATCH 5/5] Derive Debug and Clone --- lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib.rs b/lib.rs index 62a92d1..a020dc4 100644 --- a/lib.rs +++ b/lib.rs @@ -37,8 +37,8 @@ pub type FxBuildHasher = BuildHasherDefault; /// A `HashMap` using a default Fx hasher. /// -#[derive(Default)] #[repr(transparent)] +#[derive(Debug, Clone, Default)] pub struct FxHashMap(HashMap); impl FxHashMap { @@ -84,8 +84,8 @@ where } /// A `HashSet` using a default Fx hasher. -#[derive(Default)] #[repr(transparent)] +#[derive(Debug, Clone, Default)] pub struct FxHashSet(HashSet); impl FxHashSet {