#![allow(dead_code)]
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct BucketEntry {
pub key: u64,
pub value: u64,
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct HashBucket {
buckets: Vec<Vec<BucketEntry>>,
count: usize,
}
#[allow(dead_code)]
pub fn new_hash_bucket(n_buckets: usize) -> HashBucket {
let n = if n_buckets == 0 { 16 } else { n_buckets };
HashBucket {
buckets: vec![Vec::new(); n],
count: 0,
}
}
fn bucket_idx(hb: &HashBucket, key: u64) -> usize {
(key as usize) % hb.buckets.len()
}
#[allow(dead_code)]
pub fn hb_insert(hb: &mut HashBucket, key: u64, value: u64) {
let idx = bucket_idx(hb, key);
for entry in &mut hb.buckets[idx] {
if entry.key == key {
entry.value = value;
return;
}
}
hb.buckets[idx].push(BucketEntry { key, value });
hb.count += 1;
}
#[allow(dead_code)]
pub fn hb_get(hb: &HashBucket, key: u64) -> Option<u64> {
let idx = bucket_idx(hb, key);
hb.buckets[idx]
.iter()
.find(|e| e.key == key)
.map(|e| e.value)
}
#[allow(dead_code)]
pub fn hb_remove(hb: &mut HashBucket, key: u64) -> Option<u64> {
let idx = bucket_idx(hb, key);
let bucket = &mut hb.buckets[idx];
if let Some(pos) = bucket.iter().position(|e| e.key == key) {
let val = bucket.remove(pos).value;
hb.count -= 1;
Some(val)
} else {
None
}
}
#[allow(dead_code)]
pub fn hb_contains(hb: &HashBucket, key: u64) -> bool {
hb_get(hb, key).is_some()
}
#[allow(dead_code)]
pub fn hb_count(hb: &HashBucket) -> usize {
hb.count
}
#[allow(dead_code)]
pub fn hb_bucket_count(hb: &HashBucket) -> usize {
hb.buckets.len()
}
#[allow(dead_code)]
pub fn hb_clear(hb: &mut HashBucket) {
for bucket in &mut hb.buckets {
bucket.clear();
}
hb.count = 0;
}
#[allow(dead_code)]
pub fn hb_keys(hb: &HashBucket) -> Vec<u64> {
hb.buckets
.iter()
.flat_map(|b| b.iter().map(|e| e.key))
.collect()
}
#[allow(dead_code)]
pub fn hb_load_factor(hb: &HashBucket) -> f32 {
hb.count as f32 / hb.buckets.len() as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_insert_get() {
let mut hb = new_hash_bucket(8);
hb_insert(&mut hb, 1, 100);
assert_eq!(hb_get(&hb, 1), Some(100));
}
#[test]
fn test_update() {
let mut hb = new_hash_bucket(8);
hb_insert(&mut hb, 5, 10);
hb_insert(&mut hb, 5, 20);
assert_eq!(hb_get(&hb, 5), Some(20));
assert_eq!(hb_count(&hb), 1);
}
#[test]
fn test_remove() {
let mut hb = new_hash_bucket(8);
hb_insert(&mut hb, 3, 300);
assert_eq!(hb_remove(&mut hb, 3), Some(300));
assert!(!hb_contains(&hb, 3));
}
#[test]
fn test_contains() {
let mut hb = new_hash_bucket(8);
hb_insert(&mut hb, 7, 77);
assert!(hb_contains(&hb, 7));
assert!(!hb_contains(&hb, 8));
}
#[test]
fn test_count() {
let mut hb = new_hash_bucket(4);
hb_insert(&mut hb, 1, 1);
hb_insert(&mut hb, 2, 2);
assert_eq!(hb_count(&hb), 2);
}
#[test]
fn test_clear() {
let mut hb = new_hash_bucket(8);
hb_insert(&mut hb, 1, 1);
hb_clear(&mut hb);
assert_eq!(hb_count(&hb), 0);
}
#[test]
fn test_keys() {
let mut hb = new_hash_bucket(8);
hb_insert(&mut hb, 10, 1);
hb_insert(&mut hb, 20, 2);
let mut keys = hb_keys(&hb);
keys.sort();
assert_eq!(keys, vec![10, 20]);
}
#[test]
fn test_collision_same_bucket() {
let mut hb = new_hash_bucket(1);
hb_insert(&mut hb, 1, 111);
hb_insert(&mut hb, 2, 222);
assert_eq!(hb_get(&hb, 1), Some(111));
assert_eq!(hb_get(&hb, 2), Some(222));
}
#[test]
fn test_load_factor() {
let mut hb = new_hash_bucket(10);
hb_insert(&mut hb, 1, 1);
hb_insert(&mut hb, 2, 2);
let lf = hb_load_factor(&hb);
assert!((lf - 0.2_f32).abs() < 1e-5);
}
}