Skip to main content

axhash_map/
lib.rs

1use core::fmt;
2use core::hash::{BuildHasher, BuildHasherDefault, Hash};
3use core::ops::{Deref, DerefMut, Index};
4
5pub use axhash_core::{AxBuildHasher, AxHasher};
6pub use hashbrown::{HashMap as RawHashMap, HashSet as RawHashSet};
7
8pub type HashMap<K, V> = RawHashMap<K, V, BuildHasherDefault<AxHasher>>;
9pub type HashSet<T> = RawHashSet<T, BuildHasherDefault<AxHasher>>;
10
11pub struct AxHashMap<K, V, S = BuildHasherDefault<AxHasher>>(RawHashMap<K, V, S>);
12
13impl<K, V> AxHashMap<K, V, BuildHasherDefault<AxHasher>> {
14    #[inline]
15    pub fn new() -> Self {
16        Self(RawHashMap::with_hasher(BuildHasherDefault::default()))
17    }
18    #[inline]
19    pub fn with_capacity(capacity: usize) -> Self {
20        Self(RawHashMap::with_capacity_and_hasher(
21            capacity,
22            BuildHasherDefault::default(),
23        ))
24    }
25}
26
27impl<K, V, S: BuildHasher> AxHashMap<K, V, S> {
28    #[inline]
29    pub fn with_hasher(hasher: S) -> Self {
30        Self(RawHashMap::with_hasher(hasher))
31    }
32
33    #[inline]
34    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
35        Self(RawHashMap::with_capacity_and_hasher(capacity, hasher))
36    }
37    #[inline]
38    pub fn into_inner(self) -> RawHashMap<K, V, S> {
39        self.0
40    }
41}
42
43impl<K, V, S> Deref for AxHashMap<K, V, S> {
44    type Target = RawHashMap<K, V, S>;
45
46    #[inline]
47    fn deref(&self) -> &Self::Target {
48        &self.0
49    }
50}
51
52impl<K, V, S> DerefMut for AxHashMap<K, V, S> {
53    #[inline]
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.0
56    }
57}
58
59impl<K, V> Default for AxHashMap<K, V, BuildHasherDefault<AxHasher>> {
60    #[inline]
61    fn default() -> Self {
62        Self::new()
63    }
64}
65
66impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for AxHashMap<K, V, S> {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        self.0.fmt(f)
69    }
70}
71
72impl<K: Clone, V: Clone, S: Clone> Clone for AxHashMap<K, V, S> {
73    #[inline]
74    fn clone(&self) -> Self {
75        Self(self.0.clone())
76    }
77}
78
79impl<K: Hash + Eq, V: PartialEq, S: BuildHasher> PartialEq for AxHashMap<K, V, S> {
80    fn eq(&self, other: &Self) -> bool {
81        self.0 == other.0
82    }
83}
84
85impl<K: Hash + Eq, V: Eq, S: BuildHasher> Eq for AxHashMap<K, V, S> {}
86
87impl<K, Q, V, S> Index<&Q> for AxHashMap<K, V, S>
88where
89    K: Hash + Eq + core::borrow::Borrow<Q>,
90    Q: Hash + Eq + ?Sized,
91    S: BuildHasher,
92{
93    type Output = V;
94
95    #[inline]
96    fn index(&self, key: &Q) -> &Self::Output {
97        self.0.index(key)
98    }
99}
100
101impl<K: Hash + Eq, V> FromIterator<(K, V)> for AxHashMap<K, V, BuildHasherDefault<AxHasher>> {
102    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
103        let iter = iter.into_iter();
104        let (lower, _) = iter.size_hint();
105        let mut map = Self::with_capacity(lower);
106        map.extend(iter);
107        map
108    }
109}
110
111impl<K: Hash + Eq, V, S: BuildHasher> Extend<(K, V)> for AxHashMap<K, V, S> {
112    #[inline]
113    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
114        self.0.extend(iter);
115    }
116}
117
118impl<'a, K: Hash + Eq + Copy, V: Copy, S: BuildHasher> Extend<(&'a K, &'a V)>
119    for AxHashMap<K, V, S>
120{
121    #[inline]
122    fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
123        self.0.extend(iter);
124    }
125}
126
127impl<K, V, S> IntoIterator for AxHashMap<K, V, S> {
128    type Item = (K, V);
129    type IntoIter = hashbrown::hash_map::IntoIter<K, V>;
130
131    #[inline]
132    fn into_iter(self) -> Self::IntoIter {
133        self.0.into_iter()
134    }
135}
136
137impl<'a, K, V, S> IntoIterator for &'a AxHashMap<K, V, S> {
138    type Item = (&'a K, &'a V);
139    type IntoIter = hashbrown::hash_map::Iter<'a, K, V>;
140
141    #[inline]
142    fn into_iter(self) -> Self::IntoIter {
143        self.0.iter()
144    }
145}
146
147impl<'a, K, V, S> IntoIterator for &'a mut AxHashMap<K, V, S> {
148    type Item = (&'a K, &'a mut V);
149    type IntoIter = hashbrown::hash_map::IterMut<'a, K, V>;
150
151    #[inline]
152    fn into_iter(self) -> Self::IntoIter {
153        self.0.iter_mut()
154    }
155}
156
157impl<K, V, S> From<RawHashMap<K, V, S>> for AxHashMap<K, V, S> {
158    #[inline]
159    fn from(inner: RawHashMap<K, V, S>) -> Self {
160        Self(inner)
161    }
162}
163
164impl<K, V, S> From<AxHashMap<K, V, S>> for RawHashMap<K, V, S> {
165    #[inline]
166    fn from(wrapper: AxHashMap<K, V, S>) -> Self {
167        wrapper.0
168    }
169}
170
171pub struct AxHashSet<T, S = BuildHasherDefault<AxHasher>>(RawHashSet<T, S>);
172
173impl<T> AxHashSet<T, BuildHasherDefault<AxHasher>> {
174    #[inline]
175    pub fn new() -> Self {
176        Self(RawHashSet::with_hasher(BuildHasherDefault::default()))
177    }
178
179    #[inline]
180    pub fn with_capacity(capacity: usize) -> Self {
181        Self(RawHashSet::with_capacity_and_hasher(
182            capacity,
183            BuildHasherDefault::default(),
184        ))
185    }
186}
187
188impl<T, S: BuildHasher> AxHashSet<T, S> {
189    #[inline]
190    pub fn with_hasher(hasher: S) -> Self {
191        Self(RawHashSet::with_hasher(hasher))
192    }
193
194    #[inline]
195    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
196        Self(RawHashSet::with_capacity_and_hasher(capacity, hasher))
197    }
198
199    #[inline]
200    pub fn into_inner(self) -> RawHashSet<T, S> {
201        self.0
202    }
203}
204
205impl<T, S> Deref for AxHashSet<T, S> {
206    type Target = RawHashSet<T, S>;
207
208    #[inline]
209    fn deref(&self) -> &Self::Target {
210        &self.0
211    }
212}
213
214impl<T, S> DerefMut for AxHashSet<T, S> {
215    #[inline]
216    fn deref_mut(&mut self) -> &mut Self::Target {
217        &mut self.0
218    }
219}
220
221impl<T> Default for AxHashSet<T, BuildHasherDefault<AxHasher>> {
222    #[inline]
223    fn default() -> Self {
224        Self::new()
225    }
226}
227
228impl<T: fmt::Debug, S> fmt::Debug for AxHashSet<T, S> {
229    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230        self.0.fmt(f)
231    }
232}
233
234impl<T: Clone, S: Clone> Clone for AxHashSet<T, S> {
235    #[inline]
236    fn clone(&self) -> Self {
237        Self(self.0.clone())
238    }
239}
240
241impl<T: Hash + Eq, S: BuildHasher> PartialEq for AxHashSet<T, S> {
242    fn eq(&self, other: &Self) -> bool {
243        self.0 == other.0
244    }
245}
246
247impl<T: Hash + Eq, S: BuildHasher> Eq for AxHashSet<T, S> {}
248
249impl<T: Hash + Eq> FromIterator<T> for AxHashSet<T, BuildHasherDefault<AxHasher>> {
250    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
251        let iter = iter.into_iter();
252        let (lower, _) = iter.size_hint();
253        let mut set = Self::with_capacity(lower);
254        set.extend(iter);
255        set
256    }
257}
258
259impl<T: Hash + Eq, S: BuildHasher> Extend<T> for AxHashSet<T, S> {
260    #[inline]
261    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
262        self.0.extend(iter);
263    }
264}
265
266impl<'a, T: Hash + Eq + Copy, S: BuildHasher> Extend<&'a T> for AxHashSet<T, S> {
267    #[inline]
268    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
269        self.0.extend(iter);
270    }
271}
272
273impl<T, S> IntoIterator for AxHashSet<T, S> {
274    type Item = T;
275    type IntoIter = hashbrown::hash_set::IntoIter<T>;
276
277    #[inline]
278    fn into_iter(self) -> Self::IntoIter {
279        self.0.into_iter()
280    }
281}
282
283impl<'a, T, S> IntoIterator for &'a AxHashSet<T, S> {
284    type Item = &'a T;
285    type IntoIter = hashbrown::hash_set::Iter<'a, T>;
286
287    #[inline]
288    fn into_iter(self) -> Self::IntoIter {
289        self.0.iter()
290    }
291}
292
293impl<T, S> From<RawHashSet<T, S>> for AxHashSet<T, S> {
294    #[inline]
295    fn from(inner: RawHashSet<T, S>) -> Self {
296        Self(inner)
297    }
298}
299
300impl<T, S> From<AxHashSet<T, S>> for RawHashSet<T, S> {
301    #[inline]
302    fn from(wrapper: AxHashSet<T, S>) -> Self {
303        wrapper.0
304    }
305}
306
307#[cfg(test)]
308mod tests {
309    use super::*;
310    use core::hash::BuildHasherDefault;
311
312    #[test]
313    fn map_basic_operations() {
314        let mut map: AxHashMap<&str, u32> = AxHashMap::new();
315        assert!(map.is_empty());
316
317        map.insert("one", 1);
318        map.insert("two", 2);
319        map.insert("three", 3);
320
321        assert_eq!(map.len(), 3);
322        assert_eq!(map["one"], 1);
323        assert_eq!(map.get("two"), Some(&2));
324        assert_eq!(map.get("missing"), None);
325
326        map.remove("two");
327        assert_eq!(map.len(), 2);
328    }
329
330    #[test]
331    fn map_with_capacity() {
332        let map: AxHashMap<u32, u32> = AxHashMap::with_capacity(128);
333        assert!(map.capacity() >= 128);
334    }
335
336    #[test]
337    fn map_default() {
338        let map: AxHashMap<u64, u64> = AxHashMap::default();
339        assert!(map.is_empty());
340    }
341
342    #[test]
343    fn map_from_iterator() {
344        let pairs = vec![("a", 1u32), ("b", 2), ("c", 3)];
345        let map: AxHashMap<&str, u32> = pairs.into_iter().collect();
346        assert_eq!(map.len(), 3);
347        assert_eq!(map["b"], 2);
348    }
349
350    #[test]
351    fn map_extend() {
352        let mut map: AxHashMap<u32, u32> = AxHashMap::new();
353        map.extend([(1, 10), (2, 20)]);
354        map.extend([(3, 30)]);
355        assert_eq!(map.len(), 3);
356        assert_eq!(map[&2], 20);
357    }
358
359    #[test]
360    fn map_iter() {
361        let map: AxHashMap<u32, u32> = [(1, 10), (2, 20)].into_iter().collect();
362        let mut sum = 0u32;
363        for (_, v) in &map {
364            sum += v;
365        }
366        assert_eq!(sum, 30);
367    }
368
369    #[test]
370    fn map_into_inner_roundtrip() {
371        let mut map: AxHashMap<&str, i32> = AxHashMap::new();
372        map.insert("x", 99);
373        let raw: RawHashMap<&str, i32, BuildHasherDefault<AxHasher>> = map.into_inner();
374        assert_eq!(raw["x"], 99);
375        let wrapped: AxHashMap<&str, i32> = raw.into();
376        assert_eq!(wrapped["x"], 99);
377    }
378
379    #[test]
380    fn map_seeded_hasher() {
381        let hasher = AxBuildHasher::with_seed(0x1234_5678_9abc_def0);
382        let mut map: AxHashMap<&str, u32, AxBuildHasher> = AxHashMap::with_hasher(hasher);
383        map.insert("seeded", 7);
384        assert_eq!(map["seeded"], 7);
385    }
386
387    #[test]
388    fn alias_hashmap_basic() {
389        let mut map: HashMap<&str, u32> = HashMap::with_hasher(BuildHasherDefault::default());
390        map.insert("hello", 42);
391        assert_eq!(map["hello"], 42);
392    }
393
394    #[test]
395    fn alias_hashmap_collect() {
396        let map: HashMap<&str, u32> = [("a", 1u32), ("b", 2), ("c", 3)]
397            .into_iter()
398            .collect::<RawHashMap<_, _, BuildHasherDefault<AxHasher>>>();
399        assert_eq!(map.len(), 3);
400    }
401
402    #[test]
403    fn set_basic_operations() {
404        let mut set: AxHashSet<u32> = AxHashSet::new();
405        assert!(set.is_empty());
406
407        set.insert(1);
408        set.insert(2);
409        set.insert(2); // duplicate
410        set.insert(3);
411
412        assert_eq!(set.len(), 3);
413        assert!(set.contains(&1));
414        assert!(!set.contains(&99));
415
416        set.remove(&2);
417        assert_eq!(set.len(), 2);
418    }
419
420    #[test]
421    fn set_with_capacity() {
422        let set: AxHashSet<u64> = AxHashSet::with_capacity(64);
423        assert!(set.capacity() >= 64);
424    }
425
426    #[test]
427    fn set_default() {
428        let set: AxHashSet<u64> = AxHashSet::default();
429        assert!(set.is_empty());
430    }
431
432    #[test]
433    fn set_from_iterator() {
434        let set: AxHashSet<u32> = [1u32, 2, 3, 2, 1].into_iter().collect();
435        assert_eq!(set.len(), 3);
436    }
437
438    #[test]
439    fn set_extend() {
440        let mut set: AxHashSet<u32> = AxHashSet::new();
441        set.extend([1u32, 2, 3]);
442        set.extend([3u32, 4, 5]);
443        assert_eq!(set.len(), 5);
444    }
445
446    #[test]
447    fn set_set_operations() {
448        let a: AxHashSet<u32> = [1, 2, 3].into_iter().collect();
449        let b: AxHashSet<u32> = [2, 3, 4].into_iter().collect();
450
451        let union: AxHashSet<u32> = a.union(&b).copied().collect();
452        assert_eq!(union.len(), 4);
453
454        let inter: AxHashSet<u32> = a.intersection(&b).copied().collect();
455        assert_eq!(inter.len(), 2);
456    }
457
458    #[test]
459    fn set_into_inner_roundtrip() {
460        let mut set: AxHashSet<i32> = AxHashSet::new();
461        set.insert(42);
462        let raw: RawHashSet<i32, BuildHasherDefault<AxHasher>> = set.into_inner();
463        assert!(raw.contains(&42));
464        let wrapped: AxHashSet<i32> = raw.into();
465        assert!(wrapped.contains(&42));
466    }
467
468    #[test]
469    fn alias_hashset_basic() {
470        let mut set: HashSet<u32> = HashSet::with_hasher(BuildHasherDefault::default());
471        set.insert(1);
472        set.insert(2);
473        set.insert(2);
474        assert_eq!(set.len(), 2);
475    }
476}