std.hash
std.hash defines the shared Hasher, Hashable, and HashKey interfaces and exposes FNV-1a, CRC-32/IEEE, and CRC-32C hashers. Digest types belong to each hasher, so 32-bit and 64-bit hashes keep their natural unsigned width.
How It Works
Hasher provides write for streaming bytes into a concrete hasher. Concrete hashers expose their own finalize return type.
import std.bytes;
import std.hash;
fn main() {
var h32 = hash.fnv32a.Fnv32a();
h32.write(bytes.Bytes("a"));
assert h32.finalize() == 0xe40c292c;
var h64 = hash.fnv64a.Fnv64a();
h64.write(bytes.Bytes("a"));
assert h64.finalize() == 0xaf63dc4c8601ec8c;
var crc = hash.crc32.Crc32();
crc.write(bytes.Bytes("hello"));
assert crc.finalize() == 0x3610a686;
var crc32c = hash.crc32c.Crc32c();
crc32c.write(bytes.Bytes("123456789"));
assert crc32c.finalize() == 0xe3069283;
}CRC-32 Variants
crc32.Crc32 implements the zlib-compatible CRC-32/IEEE checksum used by PKZIP and Ethernet. crc32c.Crc32c implements CRC-32C Castagnoli. Use crc32.sum or crc32c.sum for the common one-shot case.
import std.bytes;
import std.hash;
fn main() {
assert hash.crc32.sum(bytes.Bytes("123456789")) == 0xcbf43926;
assert hash.crc32c.sum(bytes.Bytes("123456789")) == 0xe3069283;
var hasher = hash.crc32c.Crc32c();
hasher.write(bytes.Bytes("1234"));
hasher.write(bytes.Bytes("56789"));
assert hasher.finalize() == 0xe3069283;
}Hashable Values
Implement Hashable.hash when a value can feed itself into a hasher selected by a generic constraint. hash describes an ordered semantic expansion; it does not choose or promise a stable hash-table finalizer.
import std.hash;
import std.bytes;
let hash_calls = ThreadLocal<i32>(() -> i32 {
return 0;
});
struct Tag: hash.Hashable {
fn hash<H: hash.Hasher>(self, hasher: &H) {
hasher.write(bytes.Bytes(""));
hash_calls.update((count: &i32) -> void {
count = *count + 1;
});
}
}
fn main() {
var hasher = hash.fnv32a.Fnv32a();
let tag = Tag {};
tag.hash(&hasher);
assert hash_calls.read((count: i32) -> i32 {
return count;
}) == 1;
}Hash Keys
HashKey adds one canonical semantic equality to Hashable:
interface HashKey: Hashable {
fn equal(self, other: Self) -> bool;
}equal must be an equivalence relation, and equal values must feed identical semantic expansions to every Hasher. A violation is a collection-local logic error, never undefined behavior. Standard integer, boolean, payloadless-enum, str, and Bytes keys use their natural identity. IEEE floats do not implement HashKey automatically because equality is not reflexive for NaN.
An alternate identity requires an explicit nominal wrapper rather than a per-map callback or policy type. For example, a case-folded name stores its normalized spelling and defines both equal and hash from that spelling. This makes maps with different notions of identity different static types.
Ownership, Allocation, Errors, And Unspecified Behavior
Hashers own only their small algorithm state and borrow Bytes input during write or one-shot sum calls. The public hash helpers do not allocate and do not throw.
These public algorithms are deterministic checksums and hash functions, not cryptographic primitives. HashMap and Set do not use them as caller-selected table finalizers: each collection privately applies a keyed, evolvable finalizer to its key's Hashable expansion. Seeds, final table hashes, and physical table layout are not exposed here.
The collection types themselves implement neither Hashable nor HashKey. Set.equal compares extensional membership using the element type's existing canonical HashKey identity; it does not make the set a hashable key. HashMap has no collection equality operation, and there is no general Eq interface.
Use the external zynx-crypto package described by the cryptographic boundary for cryptographic digests and MACs, and std.collections for hash-backed maps and sets.
API Reference
Interfaces
| Interface | Methods | Description |
|---|---|---|
Hasher | write | Streaming hash input interface. finalize is concrete-hasher-specific. |
Hashable | hash | Values that can feed themselves into a Hasher. |
HashKey | equal, inherited hash | Canonical equivalence and matching semantic hash expansion for keyed collections. |
Types
| Type | Kind | Public fields | Methods | Description |
|---|---|---|---|---|
crc32.Crc32 | struct: Hasher | None | write, finalize | CRC-32/IEEE hasher compatible with zlib, PKZIP, and Ethernet. |
crc32c.Crc32c | struct: Hasher | None | write, finalize | CRC-32C Castagnoli hasher. |
fnv32a.Fnv32a | struct: Hasher | None | write, finalize | FNV-1a 32-bit hasher. |
fnv64a.Fnv64a | struct: Hasher | None | write, finalize | FNV-1a 64-bit hasher. |
Methods
| Method | Signature | Parameters | Returns | Description |
|---|---|---|---|---|
Hasher.write | write(data: Bytes) | data: bytes to add | void | Adds bytes to the stream. |
Hashable.hash | hash<H: Hasher>(self, hasher: &H) | hasher: destination hasher | void | Feeds this value into a hasher. |
HashKey.equal | equal(self, other: Self) -> bool | other: key to compare | bool | Tests the key type's one canonical equivalence relation. Equal keys must have identical hash expansions. |
Crc32.finalize | finalize() -> u32 | None | u32 | Returns the 32-bit CRC checksum. |
Crc32c.finalize | finalize() -> u32 | None | u32 | Returns the 32-bit CRC-32C checksum. |
crc32.sum | sum(data: Bytes) -> u32 | data: bytes to hash | u32 | Computes a one-shot CRC-32/IEEE checksum. |
crc32c.sum | sum(data: Bytes) -> u32 | data: bytes to hash | u32 | Computes a one-shot CRC-32C checksum. |
Fnv32a.finalize | finalize() -> u32 | None | u32 | Returns the 32-bit unsigned digest. |
Fnv64a.finalize | finalize() -> u64 | None | u64 | Returns the 64-bit unsigned digest. |
Status
std.hash is the current public non-cryptographic hash facade. For the full exported surface, see Standard Library Inventory.