pub struct KeyInterner<K> { /* private fields */ }Expand description
Monotonic key interner that assigns a u64 handle to each unique key.
Maps external keys to compact u64 handles for efficient storage and lookup.
Handles are assigned sequentially starting from 0 and never reused.
§Type Parameters
K: Key type, must beEq + Hash + Clone
§Example
use cachekit::ds::KeyInterner;
let mut interner = KeyInterner::new();
// Intern returns a handle
let handle = interner.intern(&"my_key");
assert_eq!(handle, 0); // First key gets handle 0
// Same key returns same handle
assert_eq!(interner.intern(&"my_key"), 0);
// Different key gets next handle
assert_eq!(interner.intern(&"other_key"), 1);
// Resolve handle back to key
assert_eq!(interner.resolve(0), Some(&"my_key"));§Use Case: Frequency Tracking
use cachekit::ds::KeyInterner;
use std::collections::HashMap;
let mut interner = KeyInterner::new();
let mut freq: HashMap<u64, u32> = HashMap::new();
// Track access frequency using handles (cheaper than cloning keys)
fn access(interner: &mut KeyInterner<String>, freq: &mut HashMap<u64, u32>, key: &str) {
let handle = interner.intern(&key.to_string());
*freq.entry(handle).or_insert(0) += 1;
}
access(&mut interner, &mut freq, "page_a");
access(&mut interner, &mut freq, "page_a");
access(&mut interner, &mut freq, "page_b");
let handle_a = interner.get_handle(&"page_a".to_string()).unwrap();
assert_eq!(freq[&handle_a], 2);Implementations§
Source§impl<K> KeyInterner<K>
impl<K> KeyInterner<K>
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty interner.
§Example
use cachekit::ds::KeyInterner;
let interner: KeyInterner<String> = KeyInterner::new();
assert!(interner.is_empty());Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Creates an interner with pre-allocated capacity.
Pre-allocates space for capacity keys to avoid rehashing during growth.
§Example
use cachekit::ds::KeyInterner;
let interner: KeyInterner<String> = KeyInterner::with_capacity(1000);
assert!(interner.is_empty());Sourcepub fn intern(&mut self, key: &K) -> u64
pub fn intern(&mut self, key: &K) -> u64
Returns the handle for key, inserting it if missing.
If the key is already interned, returns the existing handle. Otherwise, assigns the next sequential handle and stores the key.
§Example
use cachekit::ds::KeyInterner;
let mut interner = KeyInterner::new();
// First key gets handle 0
let h1 = interner.intern(&"key_a");
assert_eq!(h1, 0);
// Second key gets handle 1
let h2 = interner.intern(&"key_b");
assert_eq!(h2, 1);
// Same key returns same handle (no new entry)
let h1_again = interner.intern(&"key_a");
assert_eq!(h1_again, 0);
assert_eq!(interner.len(), 2); // Still only 2 keysSourcepub fn get_handle(&self, key: &K) -> Option<u64>
pub fn get_handle(&self, key: &K) -> Option<u64>
Returns the handle for key if it exists.
Does not insert the key if missing.
§Example
use cachekit::ds::KeyInterner;
let mut interner = KeyInterner::new();
let handle = interner.intern(&"existing");
assert_eq!(interner.get_handle(&"existing"), Some(handle));
assert_eq!(interner.get_handle(&"missing"), None);Sourcepub fn resolve(&self, handle: u64) -> Option<&K>
pub fn resolve(&self, handle: u64) -> Option<&K>
Resolves a handle to its original key.
Returns None if the handle is out of bounds.
§Example
use cachekit::ds::KeyInterner;
let mut interner = KeyInterner::new();
let handle = interner.intern(&"my_key");
assert_eq!(interner.resolve(handle), Some(&"my_key"));
assert_eq!(interner.resolve(999), None); // Invalid handleSourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of interned keys.
§Example
use cachekit::ds::KeyInterner;
let mut interner = KeyInterner::new();
assert_eq!(interner.len(), 0);
interner.intern(&"a");
interner.intern(&"b");
assert_eq!(interner.len(), 2);
// Re-interning same key doesn't increase count
interner.intern(&"a");
assert_eq!(interner.len(), 2);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if no keys are interned.
§Example
use cachekit::ds::KeyInterner;
let mut interner: KeyInterner<&str> = KeyInterner::new();
assert!(interner.is_empty());
interner.intern(&"key");
assert!(!interner.is_empty());Sourcepub fn clear_shrink(&mut self)
pub fn clear_shrink(&mut self)
Clears all interned keys and shrinks internal storage.
After calling this, all previously returned handles become invalid.
§Example
use cachekit::ds::KeyInterner;
let mut interner = KeyInterner::new();
let handle = interner.intern(&"key");
assert_eq!(interner.resolve(handle), Some(&"key"));
interner.clear_shrink();
assert!(interner.is_empty());
assert_eq!(interner.resolve(handle), None); // Handle now invalidSourcepub fn approx_bytes(&self) -> usize
pub fn approx_bytes(&self) -> usize
Returns an approximate memory footprint in bytes.
§Example
use cachekit::ds::KeyInterner;
let mut interner: KeyInterner<String> = KeyInterner::new();
let base_bytes = interner.approx_bytes();
// Add some keys
for i in 0..100 {
interner.intern(&format!("key_{}", i));
}
assert!(interner.approx_bytes() > base_bytes);