# mwhash
A fast, non-cryptographic `u32` hash. `no_std`, zero dependencies, zero allocations.
Useful for: integrity checks on packets, checksums, fast buffer comparison, hash tables, embedded projects.
Not suitable for cryptography.
---
## Performance
Benchmark results (seed = `0x12345678`) are shown below:
```text
----------------------------------------------------------------------------------------------------
1 GB | size: 1048576.00 KB | iters: 3 | total: 979.626ms | per call: 326.542ms | throughput: 3.29 GB/s
----------------------------------------------------------------------------------------------------
```
* **64 KB:** L1/L2 cache.
* **1 MB:** L3 cache.
* **1 GB:** main memory.
> **Environment:*** Tested on AMD64 architecture (Processor: [Intel Core Ultra 5 125h], RAM: [16 GB lpddr5x 6000MT/s]).
> **Source code:** [examples/benchmark.rs](./examples/benchmark.rs)
---
## Installation
```toml
[dependencies]
mwhash = "0.1.0"
```
---
## Examples
### One-shot hashing
Use this when all your data is already in memory.
```rust
use mwhash::mwhash;
let hash = mwhash(b"hello mwhash");
println!("Result: {:08x}", hash);
assert_ne!(hash, 0);
```
### Incremental hashing
Use this when data arrives in chunks — e.g. from a file or a network stream. No need to keep the whole buffer in memory.
```rust
use mwhash::{Hasher, mwhash};
let mut h = Hasher::new();
h.update(b"hello");
h.update(b" rust");
let hash = h.finish();
println!("Incremental hash: {:08x}", hash);
assert_eq!(hash, mwhash(b"hello rust"));
```
### Hashing with a numeric seed
The same input produces a different hash in a different "domain" — useful for salting data or separating hash spaces.
```rust
use mwhash::{mwhash, Hasher};
let mut h = Hasher::with_seed(0x12345678);
h.update(b"codeberg better than github");
let h1 = h.finish();
println!("Seeded hash: {:08x}", h1);
assert_ne!(h1, mwhash(b"codeberg better than github"));
```
### Hashing with a string seed
More convenient than picking magic numbers by hand — the string itself is hashed into a numeric seed.
```rust
use mwhash::{mwhash, Hasher};
let mut h = Hasher::with_string_seed("My-SID-is-definitely-unique");
h.update(b"100% essential data");
let hash = h.finish();
println!("String-seeded hash: {:08x}", hash);
assert_ne!(hash, 0);
assert_ne!(hash, mwhash(b"100% essential data"));
```
### One-shot hashing with a seed
The fastest way to get a seeded hash when you don't need to process data in chunks.
```rust
use mwhash::mwhash_seeded;
let data = b"test";
let seed = 0xDEAD_BEEF;
let hash = mwhash_seeded(data, seed);
println!("Hash: {:08x}", hash);
assert_ne!(hash, mwhash::mwhash(data));
```
### Concatenation without allocation
The order of updates doesn't matter — the result matches the hash of the combined data.
```rust
use mwhash::{mwhash, mwhash_concat};
let part1 = b"foo";
let part2 = b"bar";
let combined_hash = mwhash_concat(part1, part2);
let full_hash = mwhash(b"foobar");
println!("Hash: {:08x}", combined_hash);
assert_eq!(combined_hash, full_hash);
```
### Reusing the Hasher
`reset()` returns the hasher to its initial state without new allocations — useful when processing many independent messages.
```rust
use mwhash::{mwhash_seeded, Hasher};
let custom_seed = 0x12345678;
let mut h = Hasher::with_seed(custom_seed);
h.update(b"data1");
let hash1 = h.finish();
println!("Hash 1: {:08x}", hash1);
h.reset();
h.update(b"data2");
let hash2 = h.finish();
println!("Hash 2: {:08x}", hash2);
assert_eq!(hash2, mwhash_seeded(b"data2", custom_seed));
assert_ne!(hash1, hash2);
```
After `reset()`, a hasher with a custom seed behaves exactly as it did right after creation with that same seed:
```rust
use mwhash::Hasher;
let custom_seed = 0x12345678;
let mut h = Hasher::with_seed(custom_seed);
h.update(b"some data");
println!("Hash: {:08x}", h.finish());
h.reset();
assert_eq!(h.finish(), mwhash::mwhash_seeded(b"", custom_seed));
h.update(b"new data");
println!("New hash after reset: {:08x}", h.finish());
```
---
## no_std
The library is fully `no_std`, with no `alloc`. It runs on any target, including bare metal.
---
## License
Apache License 2.0. [View License](./LICENSE)