Skip to content

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.

Zynx
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.

Zynx
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.

Zynx
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:

Zynx
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

InterfaceMethodsDescription
HasherwriteStreaming hash input interface. finalize is concrete-hasher-specific.
HashablehashValues that can feed themselves into a Hasher.
HashKeyequal, inherited hashCanonical equivalence and matching semantic hash expansion for keyed collections.

Types

TypeKindPublic fieldsMethodsDescription
crc32.Crc32struct: HasherNonewrite, finalizeCRC-32/IEEE hasher compatible with zlib, PKZIP, and Ethernet.
crc32c.Crc32cstruct: HasherNonewrite, finalizeCRC-32C Castagnoli hasher.
fnv32a.Fnv32astruct: HasherNonewrite, finalizeFNV-1a 32-bit hasher.
fnv64a.Fnv64astruct: HasherNonewrite, finalizeFNV-1a 64-bit hasher.

Methods

MethodSignatureParametersReturnsDescription
Hasher.writewrite(data: Bytes)data: bytes to addvoidAdds bytes to the stream.
Hashable.hashhash<H: Hasher>(self, hasher: &H)hasher: destination hashervoidFeeds this value into a hasher.
HashKey.equalequal(self, other: Self) -> boolother: key to compareboolTests the key type's one canonical equivalence relation. Equal keys must have identical hash expansions.
Crc32.finalizefinalize() -> u32Noneu32Returns the 32-bit CRC checksum.
Crc32c.finalizefinalize() -> u32Noneu32Returns the 32-bit CRC-32C checksum.
crc32.sumsum(data: Bytes) -> u32data: bytes to hashu32Computes a one-shot CRC-32/IEEE checksum.
crc32c.sumsum(data: Bytes) -> u32data: bytes to hashu32Computes a one-shot CRC-32C checksum.
Fnv32a.finalizefinalize() -> u32Noneu32Returns the 32-bit unsigned digest.
Fnv64a.finalizefinalize() -> u64Noneu64Returns 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.

Released under the MIT License.