pub const SLOT_COUNT: u16 = 16384;
static CRC16_TABLE: [u16; 256] = {
let mut table = [0u16; 256];
let mut i = 0;
while i < 256 {
let mut crc = (i as u16) << 8;
let mut j = 0;
while j < 8 {
if crc & 0x8000 != 0 {
crc = (crc << 1) ^ 0x1021;
} else {
crc <<= 1;
}
j += 1;
}
table[i] = crc;
i += 1;
}
table
};
fn crc16(data: &[u8]) -> u16 {
let mut crc: u16 = 0;
for &b in data {
let index = ((crc >> 8) ^ b as u16) as usize;
crc = (crc << 8) ^ CRC16_TABLE[index];
}
crc
}
pub fn hash_slot(key: &[u8]) -> u16 {
let data = extract_hash_tag(key).unwrap_or(key);
crc16(data) % SLOT_COUNT
}
fn extract_hash_tag(key: &[u8]) -> Option<&[u8]> {
let open = key.iter().position(|&b| b == b'{')?;
let close = key[open + 1..].iter().position(|&b| b == b'}')?;
if close == 0 {
return None;
}
Some(&key[open + 1..open + 1 + close])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic_hash_slot() {
let slot = hash_slot(b"mykey");
assert_eq!(slot, hash_slot(b"mykey"));
assert!(slot < SLOT_COUNT);
}
#[test]
fn slot_range() {
for i in 0..1000 {
let key = format!("key:{i}");
assert!(hash_slot(key.as_bytes()) < SLOT_COUNT);
}
}
#[test]
fn hash_tag_same_slot() {
assert_eq!(hash_slot(b"{user}.name"), hash_slot(b"{user}.email"));
assert_eq!(hash_slot(b"{order}.items"), hash_slot(b"{order}.total"));
}
#[test]
fn hash_tag_equals_bare_tag() {
assert_eq!(hash_slot(b"{foo}.bar"), hash_slot(b"foo"));
}
#[test]
fn empty_hash_tag_ignored() {
assert_eq!(hash_slot(b"{}key"), hash_slot(b"{}key"));
assert_ne!(hash_slot(b"{}key"), hash_slot(b"key"));
}
#[test]
fn no_closing_brace() {
assert_eq!(hash_slot(b"{key"), hash_slot(b"{key"));
}
#[test]
fn first_brace_pair_wins() {
assert_eq!(hash_slot(b"{a}{b}"), hash_slot(b"a"));
}
#[test]
fn empty_key() {
let slot = hash_slot(b"");
assert!(slot < SLOT_COUNT);
}
#[test]
fn known_crc16_values() {
assert_eq!(crc16(b"123456789"), 0x31C3); }
#[test]
fn extract_hash_tag_cases() {
assert_eq!(extract_hash_tag(b"{user}.name"), Some(b"user".as_slice()));
assert_eq!(extract_hash_tag(b"{}.name"), None);
assert_eq!(extract_hash_tag(b"nobraces"), None);
assert_eq!(extract_hash_tag(b"{open"), None);
assert_eq!(extract_hash_tag(b"{a}{b}"), Some(b"a".as_slice()));
assert_eq!(extract_hash_tag(b"pre{tag}post"), Some(b"tag".as_slice()));
}
}