#![allow(dead_code, unused_imports)]
#[allow(clippy::all)]
#[rustfmt::skip]
pub mod distribution;
#[allow(clippy::all)]
#[rustfmt::skip]
pub mod hash;
pub use distribution::Distribute;
pub use hash::Hasher;
use hash::Hash;
pub const HASH_CRC32: &str = "crc32";
pub const HASH_CRC32_SHORT: &str = "crc32-short";
pub const DIST_MODULA: &str = "modula";
pub fn normalize_hash_name(name: &str) -> &str {
if name.eq_ignore_ascii_case(HASH_CRC32) {
HASH_CRC32_SHORT
} else {
name
}
}
#[derive(Clone, Debug)]
pub struct Sharding {
hasher: Hasher,
distribute: Distribute,
}
impl Sharding {
pub fn new(hash_alg: &str, distribution: &str, backends: &[String]) -> Self {
Sharding {
hasher: Hasher::from(normalize_hash_name(hash_alg)),
distribute: Distribute::from(distribution, backends),
}
}
#[inline]
pub fn shard_idx(&self, key: &[u8]) -> usize {
self.distribute.index(self.hasher.hash(&key))
}
#[inline]
pub fn hash(&self, key: &[u8]) -> i64 {
self.hasher.hash(&key)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crc32_is_rewritten_to_crc32_short() {
let names: Vec<String> = (0..4).map(|i| format!("127.0.0.1:{}", 11000 + i)).collect();
let plain = Sharding::new(HASH_CRC32, DIST_MODULA, &names);
let short = Sharding::new(HASH_CRC32_SHORT, DIST_MODULA, &names);
for key in [&b"u7559723634"[..], b"abc", b"0000000000000001kkkk"] {
assert_eq!(
plain.shard_idx(key),
short.shard_idx(key),
"crc32 must equal crc32-short for {key:?}"
);
assert_eq!(plain.hash(key), short.hash(key));
}
assert_eq!(plain.hash(b"u7559723634"), 12180);
assert_eq!(plain.shard_idx(b"u7559723634"), 0);
}
}