use std::hash::{BuildHasher, Hasher};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
struct CountingHasher {
inner: fxhash::FxHasher,
}
impl Hasher for CountingHasher {
fn finish(&self) -> u64 {
self.inner.finish()
}
fn write(&mut self, bytes: &[u8]) {
self.inner.write(bytes);
}
}
#[derive(Clone)]
struct CountingBuildHasher {
count: Arc<AtomicU64>,
}
impl CountingBuildHasher {
fn new() -> Self {
Self {
count: Arc::new(AtomicU64::new(0)),
}
}
fn build_count(&self) -> u64 {
self.count.load(Ordering::Relaxed)
}
}
impl BuildHasher for CountingBuildHasher {
type Hasher = CountingHasher;
fn build_hasher(&self) -> CountingHasher {
self.count.fetch_add(1, Ordering::Relaxed);
CountingHasher {
inner: fxhash::FxHasher::default(),
}
}
}
#[test]
fn semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let mut m = tmap!("override_test/map", 4; builder.clone());
m.insert(1u32, "hello");
m.insert(2u32, "world");
assert!(
builder.build_count() > 0,
"custom hasher must be used (build_count = {})",
builder.build_count()
);
assert_eq!(m.get(&1), Some(&"hello"));
assert_eq!(m.get(&2), Some(&"world"));
}
#[test]
fn default_arm_does_not_use_counting_hasher() {
let builder = CountingBuildHasher::new();
let mut _m = tmap!("override_test/default", 4);
_m.insert(0u32, "placeholder"); assert_eq!(
builder.build_count(),
0,
"default arm must not call counting hasher"
);
}
#[test]
fn tfxmap_semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let mut m = tfxmap!("override_test/fxmap", 4; builder.clone());
m.insert(1u32, "hello");
m.insert(2u32, "world");
assert!(
builder.build_count() > 0,
"custom hasher must be used for tfxmap! (build_count = {})",
builder.build_count()
);
}
#[test]
fn tfxset_semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let mut s = tfxset!("override_test/fxset", 4; builder.clone());
s.insert(1u32);
s.insert(2u32);
assert!(
builder.build_count() > 0,
"custom hasher must be used for tfxset! (build_count = {})",
builder.build_count()
);
}
#[test]
fn tset_semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let mut s = tset!("override_test/set", 4; builder.clone());
s.insert(1u32);
s.insert(2u32);
assert!(
builder.build_count() > 0,
"custom hasher must be used for tset! (build_count = {})",
builder.build_count()
);
}
#[test]
fn tdashmap_semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let m = tdashmap!("override_test/dashmap", 4; builder.clone());
m.insert(1u32, "hello");
m.insert(2u32, "world");
assert!(
builder.build_count() > 0,
"custom hasher must be used for tdashmap! (build_count = {})",
builder.build_count()
);
}
#[test]
fn tsccmap_semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let m = tsccmap!("override_test/sccmap", 4; builder.clone());
let _ = m.insert(1u32, "hello");
let _ = m.insert(2u32, "world");
assert!(
builder.build_count() > 0,
"custom hasher must be used for tsccmap! (build_count = {})",
builder.build_count()
);
}
#[test]
fn tsccset_semicolon_arm_uses_provided_hasher() {
let builder = CountingBuildHasher::new();
let s = tsccset!("override_test/sccset", 4; builder.clone());
let _ = s.insert(1u32);
let _ = s.insert(2u32);
assert!(
builder.build_count() > 0,
"custom hasher must be used for tsccset! (build_count = {})",
builder.build_count()
);
}