1#![doc = include_str!("../README.md")]
2
3use core::fmt;
4use core::hash::{BuildHasher, BuildHasherDefault, Hash};
5use core::ops::{Deref, DerefMut};
6
7pub use axhash_core::{AxBuildHasher, AxHasher};
12
13pub use dashmap::DashMap as RawDashMap;
15
16pub use dashmap::DashSet as RawDashSet;
18
19pub use dashmap::Entry as DashEntry;
21pub use dashmap::OccupiedEntry as DashOccupiedEntry;
22pub use dashmap::VacantEntry as DashVacantEntry;
23
24pub type DashMap<K, V> = RawDashMap<K, V, BuildHasherDefault<AxHasher>>;
51
52pub type DashSet<T> = RawDashSet<T, BuildHasherDefault<AxHasher>>;
68
69pub struct AxDashMap<K, V, S = BuildHasherDefault<AxHasher>>(RawDashMap<K, V, S>);
71
72impl<K, V> AxDashMap<K, V, BuildHasherDefault<AxHasher>>
73where
74 K: Hash + Eq,
75{
76 #[inline(always)]
79 pub fn new() -> Self {
80 Self(RawDashMap::with_hasher(BuildHasherDefault::default()))
81 }
82
83 #[inline(always)]
86 pub fn with_capacity(capacity: usize) -> Self {
87 Self(RawDashMap::with_capacity_and_hasher(
88 capacity,
89 BuildHasherDefault::default(),
90 ))
91 }
92
93 #[inline(always)]
100 pub fn with_shard_amount(shard_amount: usize) -> Self {
101 Self(RawDashMap::with_hasher_and_shard_amount(
102 BuildHasherDefault::default(),
103 shard_amount,
104 ))
105 }
106
107 #[inline(always)]
110 pub fn with_capacity_and_shard_amount(capacity: usize, shard_amount: usize) -> Self {
111 Self(RawDashMap::with_capacity_and_hasher_and_shard_amount(
112 capacity,
113 BuildHasherDefault::default(),
114 shard_amount,
115 ))
116 }
117}
118
119impl<K, V, S> AxDashMap<K, V, S>
120where
121 K: Hash + Eq,
122 S: BuildHasher + Clone,
123{
124 #[inline(always)]
136 pub fn with_hasher(hasher: S) -> Self {
137 Self(RawDashMap::with_hasher(hasher))
138 }
139
140 #[inline(always)]
143 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
144 Self(RawDashMap::with_capacity_and_hasher(capacity, hasher))
145 }
146
147 #[inline(always)]
150 pub fn with_hasher_and_shard_amount(hasher: S, shard_amount: usize) -> Self {
151 Self(RawDashMap::with_hasher_and_shard_amount(
152 hasher,
153 shard_amount,
154 ))
155 }
156
157 #[inline(always)]
160 pub fn with_capacity_and_hasher_and_shard_amount(
161 capacity: usize,
162 hasher: S,
163 shard_amount: usize,
164 ) -> Self {
165 Self(RawDashMap::with_capacity_and_hasher_and_shard_amount(
166 capacity,
167 hasher,
168 shard_amount,
169 ))
170 }
171
172 #[inline(always)]
174 pub fn into_inner(self) -> RawDashMap<K, V, S> {
175 self.0
176 }
177}
178
179impl<K, V, S> Deref for AxDashMap<K, V, S> {
182 type Target = RawDashMap<K, V, S>;
183
184 #[inline(always)]
185 fn deref(&self) -> &Self::Target {
186 &self.0
187 }
188}
189
190impl<K, V, S> DerefMut for AxDashMap<K, V, S> {
191 #[inline(always)]
192 fn deref_mut(&mut self) -> &mut Self::Target {
193 &mut self.0
194 }
195}
196
197impl<K, V> Default for AxDashMap<K, V, BuildHasherDefault<AxHasher>>
200where
201 K: Hash + Eq,
202{
203 #[inline(always)]
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209impl<K, V, S> fmt::Debug for AxDashMap<K, V, S>
210where
211 K: Hash + Eq + fmt::Debug,
212 V: fmt::Debug,
213 S: BuildHasher + Clone,
214{
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 self.0.fmt(f)
217 }
218}
219
220impl<K, V> FromIterator<(K, V)> for AxDashMap<K, V, BuildHasherDefault<AxHasher>>
223where
224 K: Hash + Eq,
225{
226 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
227 let iter = iter.into_iter();
228 let (lower, _) = iter.size_hint();
229 let map = Self::with_capacity(lower);
230 iter.for_each(|(k, v)| {
231 map.insert(k, v);
232 });
233 map
234 }
235}
236
237impl<K, V, S> Extend<(K, V)> for AxDashMap<K, V, S>
238where
239 K: Hash + Eq,
240 S: BuildHasher + Clone,
241{
242 #[inline]
243 fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
244 iter.into_iter().for_each(|(k, v)| {
245 self.0.insert(k, v);
246 });
247 }
248}
249
250impl<K, V, S> From<RawDashMap<K, V, S>> for AxDashMap<K, V, S> {
253 #[inline(always)]
254 fn from(inner: RawDashMap<K, V, S>) -> Self {
255 Self(inner)
256 }
257}
258
259impl<K, V, S> From<AxDashMap<K, V, S>> for RawDashMap<K, V, S> {
260 #[inline(always)]
261 fn from(wrapper: AxDashMap<K, V, S>) -> Self {
262 wrapper.0
263 }
264}
265
266pub struct AxDashSet<T, S = BuildHasherDefault<AxHasher>>(RawDashSet<T, S>);
278
279impl<T> AxDashSet<T, BuildHasherDefault<AxHasher>>
280where
281 T: Hash + Eq,
282{
283 #[inline(always)]
286 pub fn new() -> Self {
287 Self(RawDashSet::with_hasher(BuildHasherDefault::default()))
288 }
289
290 #[inline(always)]
292 pub fn with_capacity(capacity: usize) -> Self {
293 Self(RawDashSet::with_capacity_and_hasher(
294 capacity,
295 BuildHasherDefault::default(),
296 ))
297 }
298}
299
300impl<T, S> AxDashSet<T, S>
301where
302 T: Hash + Eq,
303 S: BuildHasher + Clone,
304{
305 #[inline(always)]
307 pub fn with_hasher(hasher: S) -> Self {
308 Self(RawDashSet::with_hasher(hasher))
309 }
310
311 #[inline(always)]
314 pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
315 Self(RawDashSet::with_capacity_and_hasher(capacity, hasher))
316 }
317
318 #[inline(always)]
320 pub fn into_inner(self) -> RawDashSet<T, S> {
321 self.0
322 }
323}
324
325impl<T, S> Deref for AxDashSet<T, S> {
328 type Target = RawDashSet<T, S>;
329
330 #[inline(always)]
331 fn deref(&self) -> &Self::Target {
332 &self.0
333 }
334}
335
336impl<T, S> DerefMut for AxDashSet<T, S> {
337 #[inline(always)]
338 fn deref_mut(&mut self) -> &mut Self::Target {
339 &mut self.0
340 }
341}
342
343impl<T> Default for AxDashSet<T, BuildHasherDefault<AxHasher>>
346where
347 T: Hash + Eq,
348{
349 #[inline(always)]
350 fn default() -> Self {
351 Self::new()
352 }
353}
354
355impl<T, S> fmt::Debug for AxDashSet<T, S>
356where
357 T: Hash + Eq + fmt::Debug,
358 S: BuildHasher + Clone,
359{
360 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361 self.0.fmt(f)
362 }
363}
364
365impl<T> FromIterator<T> for AxDashSet<T, BuildHasherDefault<AxHasher>>
368where
369 T: Hash + Eq,
370{
371 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
372 let iter = iter.into_iter();
373 let (lower, _) = iter.size_hint();
374 let set = Self::with_capacity(lower);
375 iter.for_each(|v| {
376 set.insert(v);
377 });
378 set
379 }
380}
381
382impl<T, S> Extend<T> for AxDashSet<T, S>
383where
384 T: Hash + Eq,
385 S: BuildHasher + Clone,
386{
387 #[inline]
388 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
389 iter.into_iter().for_each(|v| {
390 self.0.insert(v);
391 });
392 }
393}
394
395impl<T, S> From<RawDashSet<T, S>> for AxDashSet<T, S> {
398 #[inline(always)]
399 fn from(inner: RawDashSet<T, S>) -> Self {
400 Self(inner)
401 }
402}
403
404impl<T, S> From<AxDashSet<T, S>> for RawDashSet<T, S> {
405 #[inline(always)]
406 fn from(wrapper: AxDashSet<T, S>) -> Self {
407 wrapper.0
408 }
409}
410
411#[cfg(test)]
414mod tests {
415 use super::*;
416 use core::hash::BuildHasherDefault;
417
418 #[test]
421 fn map_basic_operations() {
422 let map: AxDashMap<&str, u32> = AxDashMap::new();
423 assert!(map.is_empty());
424
425 map.insert("one", 1);
426 map.insert("two", 2);
427 map.insert("three", 3);
428
429 assert_eq!(map.len(), 3);
430 assert_eq!(*map.get("one").unwrap(), 1);
431 assert!(map.get("missing").is_none());
432
433 map.remove("two");
434 assert_eq!(map.len(), 2);
435 }
436
437 #[test]
438 fn map_with_capacity() {
439 let map: AxDashMap<u32, u32> = AxDashMap::with_capacity(1024);
440 assert!(map.is_empty());
441 }
442
443 #[test]
444 fn map_with_shard_amount() {
445 let map: AxDashMap<u32, u32> = AxDashMap::with_shard_amount(16);
446 map.insert(1, 10);
447 assert_eq!(*map.get(&1).unwrap(), 10);
448 }
449
450 #[test]
451 fn map_with_capacity_and_shard_amount() {
452 let map: AxDashMap<u32, u32> = AxDashMap::with_capacity_and_shard_amount(512, 8);
453 assert!(map.is_empty());
454 }
455
456 #[test]
457 fn map_default() {
458 let map: AxDashMap<u64, u64> = AxDashMap::default();
459 assert!(map.is_empty());
460 }
461
462 #[test]
463 fn map_seeded_hasher() {
464 let seed: u64 = 0xc0ffee_deadbeef;
465 let map: AxDashMap<&str, i32, AxBuildHasher> =
466 AxDashMap::with_hasher(AxBuildHasher::with_seed(seed));
467 map.insert("seeded", -1);
468 assert_eq!(*map.get("seeded").unwrap(), -1);
469 }
470
471 #[test]
472 fn map_entry_api() {
473 let map: AxDashMap<&str, u32> = AxDashMap::new();
474 for _ in 0..5 {
475 map.entry("counter").and_modify(|n| *n += 1).or_insert(0);
476 }
477 assert_eq!(*map.get("counter").unwrap(), 4);
478 }
479
480 #[test]
481 fn map_from_iterator() {
482 let map: AxDashMap<&str, u32> = [("a", 1u32), ("b", 2), ("c", 3)].into_iter().collect();
483 assert_eq!(map.len(), 3);
484 assert_eq!(*map.get("b").unwrap(), 2);
485 }
486
487 #[test]
488 fn map_extend() {
489 let mut map: AxDashMap<u32, u32> = AxDashMap::new();
490 map.extend([(1u32, 10), (2, 20), (3, 30)]);
491 assert_eq!(map.len(), 3);
492 assert_eq!(*map.get(&2u32).unwrap(), 20);
493 }
494
495 #[test]
496 fn map_iter() {
497 let map: AxDashMap<u32, u32> = [(1u32, 10), (2, 20), (3, 30)].into_iter().collect();
498 let sum: u32 = map.iter().map(|r| *r.value()).sum();
499 assert_eq!(sum, 60);
500 }
501
502 #[test]
503 fn map_alter() {
504 let map: AxDashMap<u32, u32> = [(1u32, 1), (2, 2), (3, 3)].into_iter().collect();
505 map.alter_all(|_, v| v * 10);
506 assert_eq!(*map.get(&1u32).unwrap(), 10);
507 assert_eq!(*map.get(&3u32).unwrap(), 30);
508 }
509
510 #[test]
511 fn map_retain() {
512 let map: AxDashMap<u32, u32> = (0u32..10).map(|i| (i, i * i)).collect();
513 map.retain(|_, v| *v > 25);
514 assert!(map.iter().all(|r| *r.value() > 25));
515 }
516
517 #[test]
518 fn map_into_read_only() {
519 let map: AxDashMap<&str, u32> = AxDashMap::new();
520 map.insert("ro", 99);
521 let ro = map.into_inner().into_read_only();
522 assert_eq!(*ro.get("ro").unwrap(), 99);
523 }
524
525 #[test]
526 fn map_into_inner_roundtrip() {
527 let map: AxDashMap<&str, i32> = AxDashMap::new();
528 map.insert("x", 99);
529 let raw: RawDashMap<&str, i32, BuildHasherDefault<AxHasher>> = map.into_inner();
530 assert_eq!(*raw.get("x").unwrap(), 99);
531 let wrapped: AxDashMap<&str, i32> = raw.into();
532 assert_eq!(*wrapped.get("x").unwrap(), 99);
533 }
534
535 #[test]
536 fn map_concurrent_insert() {
537 use std::sync::Arc;
538 let map: Arc<AxDashMap<u32, u32>> = Arc::new(AxDashMap::with_capacity(1_000));
539 let handles: Vec<_> = (0..8)
540 .map(|t| {
541 let m = Arc::clone(&map);
542 std::thread::spawn(move || {
543 for i in 0u32..125 {
544 m.insert(t * 125 + i, i);
545 }
546 })
547 })
548 .collect();
549 for h in handles {
550 h.join().unwrap();
551 }
552 assert_eq!(map.len(), 1_000);
553 }
554
555 #[test]
558 fn alias_dashmap_basic() {
559 let map: DashMap<&str, u32> = dashmap::DashMap::with_hasher(BuildHasherDefault::default());
560 map.insert("hello", 42);
561 assert_eq!(*map.get("hello").unwrap(), 42);
562 }
563
564 #[test]
567 fn set_basic_operations() {
568 let set: AxDashSet<u32> = AxDashSet::new();
569 assert!(set.is_empty());
570
571 set.insert(1);
572 set.insert(2);
573 set.insert(2); set.insert(3);
575
576 assert_eq!(set.len(), 3);
577 assert!(set.contains(&1));
578 assert!(!set.contains(&99));
579
580 set.remove(&2);
581 assert_eq!(set.len(), 2);
582 }
583
584 #[test]
585 fn set_default() {
586 let set: AxDashSet<u64> = AxDashSet::default();
587 assert!(set.is_empty());
588 }
589
590 #[test]
591 fn set_from_iterator() {
592 let set: AxDashSet<u32> = [1u32, 2, 3, 2, 1].into_iter().collect();
593 assert_eq!(set.len(), 3);
594 }
595
596 #[test]
597 fn set_extend() {
598 let mut set: AxDashSet<u32> = AxDashSet::new();
599 set.extend([1u32, 2, 3]);
600 set.extend([3u32, 4, 5]);
601 assert_eq!(set.len(), 5);
602 }
603
604 #[test]
605 fn set_iter() {
606 let set: AxDashSet<u32> = [1u32, 2, 3].into_iter().collect();
607 let sum: u32 = set.iter().map(|r| *r).sum();
608 assert_eq!(sum, 6);
609 }
610
611 #[test]
612 fn set_into_inner_roundtrip() {
613 let set: AxDashSet<i32> = AxDashSet::new();
614 set.insert(42);
615 let raw: RawDashSet<i32, BuildHasherDefault<AxHasher>> = set.into_inner();
616 assert!(raw.contains(&42));
617 let wrapped: AxDashSet<i32> = raw.into();
618 assert!(wrapped.contains(&42));
619 }
620
621 #[test]
622 fn set_concurrent_insert() {
623 use std::sync::Arc;
624 let set: Arc<AxDashSet<u32>> = Arc::new(AxDashSet::with_capacity(1_000));
625 let handles: Vec<_> = (0..8)
626 .map(|t| {
627 let s = Arc::clone(&set);
628 std::thread::spawn(move || {
629 for i in 0u32..125 {
630 s.insert(t * 125 + i);
631 }
632 })
633 })
634 .collect();
635 for h in handles {
636 h.join().unwrap();
637 }
638 assert_eq!(set.len(), 1_000);
639 }
640
641 #[test]
644 fn alias_dashset_basic() {
645 let set: DashSet<u32> = dashmap::DashSet::with_hasher(BuildHasherDefault::default());
646 set.insert(1);
647 set.insert(2);
648 set.insert(2);
649 assert_eq!(set.len(), 2);
650 }
651}