| Crates.io | hash-link |
| lib.rs | hash-link |
| version | 0.1.0 |
| created_at | 2026-01-08 03:44:21.263296+00 |
| updated_at | 2026-01-08 03:44:21.263296+00 |
| description | Keep elements insert order while searchable by hash |
| homepage | |
| repository | |
| max_upload_size | |
| id | 2029489 |
| size | 78,493 |
A container combining array insertion order with hash table fast lookup. This data structure combines:
Add dependency in Cargo.toml:
[dependencies]
hash-link = "0.1"
use hash_link::HashList;
fn main() {
let mut list = HashList::new();
// Insert elements
let idx1 = list.push("Alice".to_string());
let idx2 = list.push("Bob".to_string());
let idx3 = list.push("Charlie".to_string());
// Access using get_index
assert_eq!(list.get_index(idx1), Some(&"Alice".to_string()));
assert_eq!(list.get_index(idx2), Some(&"Bob".to_string()));
// Find elements
assert_eq!(list.index_of(&"Alice".to_string()), Some(idx1));
assert!(list.contains(&"Bob".to_string()));
// Iterate in insertion order
println!("In insertion order:");
for value in list.iter() {
println!(" {}", value.1);
}
// Output:
// Alice
// Bob
// Charlie
// Remove elements
list.remove(&"Bob".to_string());
// Use index_of to find elements
assert_eq!(list.index_of(&"Alice".to_string()), Some(idx1));
// Use pop method
if let Some(value) = list.pop() {
println!("Popped: {}", value);
}
// Clear all elements
list.clear();
}
use hash_link::HashList;
fn main() {
let vec = vec!["apple", "banana", "cherry"];
let list = HashList::from_vec(vec);
// Verify element order
let collected: Vec<&str> = list.iter().map(|(_, s)| *s).collect();
assert_eq!(collected, vec!["apple", "banana", "cherry"]);
}
Custom hash element trait for efficient hash computation:
pub trait Hashable: Eq {
/// Returns the hash value of the element
fn get_hash(&self) -> u32;
}
For custom types, implement the Hashable trait:
use hash_link::{HashList, Hashable};
#[derive(Debug, PartialEq, Eq)]
struct MyData {
value: i32,
name: String,
}
impl Hashable for MyData {
fn get_hash(&self) -> u32 {
let name_hash = self.name.get_hash();
(self.value as u32).wrapping_add(name_hash)
}
}
The library provides optimized implementations for common primitive types:
All types implementing Hashable must also implement PartialEq for equality comparison.
use hash_link::{HashList, Hashable};
fn main() {
let mut list = HashList::new();
list.push("hello".to_string());
list.push("world".to_string());
list.push("hello".to_string()); // Same hash value
let hello_hash = "hello".get_hash();
let mut iter = list.find_hash(hello_hash);
let mut found = Vec::new();
while let Some((index, value)) = iter.next() {
found.push((index, value.clone()));
assert_eq!(list.get(index), Some(value));
}
// Should contain two "hello" elements
assert_eq!(found.len(), 2);
}
Note: Indices returned by find_hash() are vector slot indices, not sorted indices of valid elements. These indices remain stable before compact() operations.
Use ElementGuard to safely modify elements while maintaining hash index synchronization:
use hash_link::HashList;
fn main() {
let mut list = HashList::new();
let idx = list.push("hello".to_string());
// Use ElementGuard to modify element
{
let mut guard = list.get_index_mut(idx).unwrap();
println!("Hash before modification: {}", guard.original_hash());
println!("Value before modification: {}", *guard);
// Modify element value
*guard = "modified".to_string();
println!("Value after modification: {}", *guard);
println!("Hash after modification: {}", guard.current_hash());
println!("Hash changed: {}", guard.hash_changed());
// ElementGuard automatically updates hash index on drop
}
// Verify lookup functionality after modification
assert!(list.index_of(&"hello".to_string()).is_none());
assert_eq!(list.index_of(&"modified".to_string()), Some(idx));
}
HashList uses intelligent resizing based on load factor:
(count() + 1) / hash_buckets.len() >= 0.75current valid element count * 2 (minimum 4)