nohash-hasher

A Rust Hasher that skips hashing entirely, turning HashMap and HashSet lookups on integer keys into a direct pass-through.

Library
Cargo
v0.2.0
71stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
27/100Needs Attention
Development Activity0
Maintenance0
Community36
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
59/100Fair
Architecture60
Code Quality55
Innovation45
Learning Curve75

nohash-hasher is a tiny Rust crate providing NoHashHasher<T>, an implementation of std::hash::Hasher that does not hash at all. For types whose Hash impl writes exactly one integer value (u8 through i64/isize, plus any type implementing the IsEnabled marker trait), it simply stores that value and returns it unchanged from finish(). This eliminates the CPU overhead of a general-purpose hashing algorithm for workloads where keys are already well-distributed integers, such as IDs, indices, or interned handles.

The crate exposes IntMap<K, V> and IntSet<T> type aliases that wire HashMap/HashSet up to BuildNoHashHasher<T> out of the box, so adopting it is usually a one-line type swap. In debug builds it also asserts that a hasher instance is never written to more than once, catching accidental misuse (multi-field hashes) that would silently corrupt hash quality in a release build. It supports no_std via a std feature flag, and has no external dependencies.

What You Get

  • NoHashHasher<T> — a std::hash::Hasher implementation that stores a single integer write and returns it as-is from finish()
  • IntMap<K, V> and IntSet<T> type aliases — drop-in HashMap/HashSet replacements pre-wired with BuildNoHashHasher
  • BuildNoHashHasher<T> — a BuildHasherDefault alias for constructing the hasher with standard collection APIs
  • The IsEnabled marker trait to opt custom integer-backed types into the no-hash fast path
  • Debug-mode safety assertions that panic on a double-write to the same hasher instance, catching misuse before it silently degrades hash quality in release

Common Use Cases

  • Using dense numeric IDs, arena indices, or interned symbol handles as HashMap/HashSet keys without paying for a general hash function
  • Building high-throughput graph, arena, or slotmap-style data structures where keys are already unique integers
  • Replacing SipHash-based default hashing in hot loops where profiling shows hashing overhead is significant
  • Implementing custom newtypes over integers (e.g. wrapped entity IDs) that opt in via IsEnabled for no-hash lookups

Under The Hood

Architecture The entire crate lives in a single src/lib.rs file of under 200 lines of logic. It defines the NoHashHasher<T> struct (a PhantomData-tagged wrapper around a u64, plus an extra bool write-guard field in debug builds), the IsEnabled marker trait blanket-implemented for the ten built-in integer primitive types, and two convenience type aliases (IntMap, IntSet) built on BuildHasherDefault<NoHashHasher<T>>. There are no submodules, no internal abstractions to trace, and no runtime dispatch — the design is intentionally as flat as a single-purpose utility crate can be, trading architectural depth for auditability.

Tech Stack The crate has zero external dependencies and targets no_std by default, only pulling in std::collections::HashMap/HashSet behind an opt-in std Cargo feature (enabled by default via [features] default = ["std"]). It relies solely on core::hash::{Hasher, BuildHasherDefault} and core::marker::PhantomData from the Rust standard library, with edition 2018 and no build scripts, macros, or codegen involved.

Code Quality Tests live inline in src/lib.rs under #[cfg(test)] mod tests and cover all ten supported integer types with both a correctness check (write_* then finish() roundtrips the value) and, in debug builds, a #[should_panic] test per type verifying the double-write guard fires. There is no separate integration test suite, no CI config visible in the shallow clone, and no linter configuration beyond a repo-root .editorconfig; the crate’s small surface area limits the practical blast radius of any latent issues. Error handling is deliberately assertion-based (panic!) rather than Result-based, appropriate for a hard misuse-invariant rather than a recoverable runtime condition.

What Makes It Unique The crate’s core idea — a Hasher that performs no hashing and simply forwards the single integer write — is a well-known micro-optimization pattern in the Rust ecosystem, but nohash-hasher packages it with a genuinely useful safety net: debug-only instrumentation that panics if a type’s Hash impl ever writes more than once, which would otherwise silently collapse hash quality (and correctness) for composite keys in a release build without that check. Combined with no_std support and zero dependencies, it’s a low-risk, easy-to-audit building block rather than a novel algorithmic contribution.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search