A lightweight, zero-dependency, no_std implementation of the 64-bit Fowler–Noll–Vo (FNV) non-cryptographic hash
function in Rust.
This crate provides high-performance implementations of the FNV-0, FNV-1, and FNV-1a algorithms using const generics to ensure zero-cost abstractions.
FNV is a non-cryptographic hash function created by Glenn Fowler, Landon Curt Noll, and Kiem-Phong Vo. It is designed to be:
- Extremely fast to compute.
- Easy to implement (only multiplication and XOR).
- Low collision rate for common data types.
It is particularly effective for small data sets like property names in compilers, object keys in scripts, or small strings.
- Zero Dependencies: Pure Rust implementation with no external requirements.
no_stdSupport: Ideal for embedded systems and low-level kernel development.- Const Generics: Uses modern Rust features to provide a generic interface for FNV variants.
- Standard Library Integration: Fully implements
core::hash::Hasherandcore::hash::BuildHasher.
Add this to your Cargo.toml:
[dependencies]
fnv64-rs = "0.1.0"The FNV algorithm is frequently used in hash maps because of its speed and low collision rate for short keys (like strings or integers).
use std::collections::HashMap;
use fnv64_rs::FnvBuildHasher;
// Initialize a HashMap using the FNV-1a BuildHasher
let mut map: HashMap<String, i32, FnvBuildHasher> = HashMap::default();
map.insert("apple".to_string(), 1);
map.insert("orange".to_string(), 2);
assert_eq!(map.get("apple"), Some(&1));
assert_eq!(map.get("orange"), Some(&2));
assert_eq!(map.get("pineapple"), None);The FNV algorithm is frequently used in hash sets because of its speed and low collision rate for short keys (like strings or integers).
use std::collections::HashMap;
use fnv64_rs::FnvBuildHasher;
// Initialize a HashSet using the FNV-1a BuildHasher
let mut set: HashSet<String, FnvBuildHasher> = HashSet::default();
set.insert("apple".to_string());
set.insert("orange".to_string());
assert!(set.contains("apple"));
assert!(set.contains("orange"));
assert!(!set.contains("pineapple"));You can use the hasher directly to compute values for specific data:
use core::hash::Hasher;
use fnv64_rs::Fnv1aHasher;
let mut hasher = Fnv1aHasher::default();
hasher.write(b"hello world");
let result = hasher.finish();
println!("Hash: {:x}", result);When the std feature is enabled, fnv64-rs provides convenient type aliases for standard library collections. These are pre-configured with FNV hashers and re-exported at the crate root for a seamless developer experience.
| Type | Hash Algorithm | Collection |
|---|---|---|
FnvHashMap<K, V> |
FNV-1a (Default) | HashMap |
FnvHashSet<V> |
FNV-1a (Default) | HashSet |
Fnv1aHashMap<K, V> |
FNV-1a | HashMap |
Fnv1aHashSet<V> |
FNV-1a | HashSet |
Fnv1HashMap<K, V> |
FNV-1 | HashMap |
Fnv1HashSet<V> |
FNV-1 | HashSet |
Fnv0HashMap<K, V> |
FNV-0 | HashMap |
Fnv0HashSet<V> |
FNV-0 | HashSet |
Tip
On Nightly Rust, these aliases also support the Allocator API, allowing you to use FNV collections with custom
memory allocators. Use --features nightly to enable this.
You can use these aliases directly without needing to manually import or configure a BuildHasher:
use fnv64_rs::{FnvHashMap, FnvHashSet};
// No complex generic boilerplate needed!
let mut map = FnvHashMap::default();
map.insert("id_01", 100);
let mut set = FnvHashSet::default();
set.insert("admin");| Variant | Implementation | Logic | Characteristics |
|---|---|---|---|
| FNV-1a | fnv64_rs::Fnv1aHasher |
(hash ^ byte) * PRIME |
Recommended. Best avalanche characteristics. |
| FNV-1 | fnv64_rs::Fnv1Hasher |
(hash * PRIME) ^ byte |
The original FNV-1 specification. |
| FNV-0 | fnv64_rs::Fnv0Hasher |
hash = 0; ... |
Deprecated. Included for historical purposes. |
| DEFAULT | fnv64_rs::FnvHasher |
(hash ^ byte) * PRIME |
Default implementation. Implements FNV-1a. |
This project is licensed under the Apache-2.0 License.