1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright 2026 FastLabs Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Fast, portable, non-cryptographic hash functions.
//!
//! APIs are grouped by family under [`cityhash`], [`xxhash`], [`murmur`], and
//! [`fnv`]. Use the free functions for complete byte slices and state types for
//! incremental input. CityHash is intentionally one-shot. Outputs that fit in
//! 64 bits also implement [`core::hash::Hasher`].
//!
//! Raw digests are stable across platforms for identical byte streams. The
//! [`core::hash`] adapters use Rust's native typed encodings and are not a
//! portable serialization format. These hashes are deterministic and are
//! **not cryptographically secure**.
//!
//! # Choosing an algorithm
//!
//! Prefer XXH3 for new checksums, cache keys, and trusted-input hash tables.
//! The CityHash, MurmurHash3, FNV-1a, XXH32, and XXH64 APIs are primarily for
//! interoperability with an existing format or data set. Choose a 128-bit
//! variant when the application needs a lower collision probability than a
//! 64-bit digest provides.
//!
//! # API model
//!
//! Choose the interface from the form of input rather than from a separate
//! implementation:
//!
//! * Call a module-level function such as [`xxhash::xxh3_64`] when the complete byte slice is
//! available.
//! * Construct a state such as [`xxhash::Xxh3_64`], call its `update` method for each slice, and
//! call `digest` when input is complete. `digest` does not consume the state, and `reset`
//! preserves its configuration.
//! * With the default `std` feature, use the same state as [`std::io::Write`] when bytes come from
//! an I/O producer.
//! * For a Rust hash collection, pass the matching builder as its [`core::hash::BuildHasher`].
//! These adapters consume Rust's typed [`core::hash::Hash`] encoding rather than a portable byte
//! serialization.
//!
//! ## Capability map
//!
//! | Variant | Complete input | Incremental state | Digest | [`Hasher`](core::hash::Hasher) / builder |
//! |---------------------|----------------------------------------------|--------------------------------------------|--------|---------------------------------------------------------------------------------------------------|
//! | CityHash32 | [`cityhash32`](cityhash::cityhash32) | — | `u32` | — |
//! | CityHash64 | [`cityhash64`](cityhash::cityhash64)* | — | `u64` | — |
//! | CityHash128 | [`cityhash128`](cityhash::cityhash128)* | — | `u128` | — |
//! | XXH32 | [`xxh32`](xxhash::xxh32) | [`Xxh32`](xxhash::Xxh32) | `u32` | [`Xxh32`](xxhash::Xxh32) / [`Xxh32Builder`](xxhash::Xxh32Builder) |
//! | XXH64 | [`xxh64`](xxhash::xxh64) | [`Xxh64`](xxhash::Xxh64) | `u64` | [`Xxh64`](xxhash::Xxh64) / [`Xxh64Builder`](xxhash::Xxh64Builder) |
//! | XXH3-64 | [`xxh3_64`](xxhash::xxh3_64)* | [`Xxh3_64`](xxhash::Xxh3_64) | `u64` | [`Xxh3_64`](xxhash::Xxh3_64) / [`Xxh3_64Builder`](xxhash::Xxh3_64Builder) |
//! | XXH3-128 | [`xxh3_128`](xxhash::xxh3_128)* | [`Xxh3_128`](xxhash::Xxh3_128) | `u128` | — |
//! | MurmurHash3 x86_32 | [`murmur3_x86_32`](murmur::murmur3_x86_32) | [`Murmur3X86_32`](murmur::Murmur3X86_32) | `u32` | [`Murmur3X86_32`](murmur::Murmur3X86_32) / [`Murmur3X86_32Builder`](murmur::Murmur3X86_32Builder) |
//! | MurmurHash3 x86_128 | [`murmur3_x86_128`](murmur::murmur3_x86_128) | [`Murmur3X86_128`](murmur::Murmur3X86_128) | `u128` | — |
//! | MurmurHash3 x64_128 | [`murmur3_x64_128`](murmur::murmur3_x64_128) | [`Murmur3X64_128`](murmur::Murmur3X64_128) | `u128` | — |
//! | FNV-1a 32 | [`fnv1a_32`](fnv::fnv1a_32)* | [`Fnv1a32`](fnv::Fnv1a32) | `u32` | [`Fnv1a32`](fnv::Fnv1a32) / [`Fnv1a32Builder`](fnv::Fnv1a32Builder) |
//! | FNV-1a 64 | [`fnv1a_64`](fnv::fnv1a_64)* | [`Fnv1a64`](fnv::Fnv1a64) | `u64` | [`Fnv1a64`](fnv::Fnv1a64) / [`Fnv1a64Builder`](fnv::Fnv1a64Builder) |
//!
//! A trailing `*` indicates additional explicitly named configuration forms.
//! [`xxhash::Xxh3_64SecretBuilder`] provides the custom-secret XXH3-64 hash-table
//! adapter. The 128-bit states do not implement [`core::hash::Hasher`] because
//! its [`finish`](core::hash::Hasher::finish) method can only return `u64`.
//! CityHash has no streaming state because bounded-memory incremental hashing
//! cannot reproduce its one-shot algorithm. MurmurHash3's `x86` and `x64`
//! labels distinguish incompatible algorithms, not target requirements.
//!
//! # Feature flags
//!
//! The crate is dependency-free and allocation-free in every feature
//! configuration. The default `std` feature integrates streaming states with
//! [`std::io`] and enables runtime CPU-feature detection for XXH3. Disable
//! default features for `no_std` targets; hardware kernels are then selected
//! only from features guaranteed by the target, with scalar code as the
//! fallback. Feature selection does not change digest values.
//!
//! ```toml
//! [dependencies]
//! hashcrew = { version = "0.1", default-features = false }
//! ```
//!
//! # Streaming input
//!
//! Call `update` when the application already receives byte slices. With the
//! default `std` feature, every incremental state can also be the destination
//! of [`std::io::copy`] or another producer that writes to [`std::io::Write`].
//! Bytes written to the state become hash input: `write` accepts the complete
//! buffer, and `flush` has no work to perform. Obtain the digest separately
//! after the producer finishes.
//!
//! ```
//! # #[cfg(feature = "std")]
//! # {
//! use std::io;
//!
//! use hashcrew::xxhash::Xxh3_64;
//! use hashcrew::xxhash::xxh3_64;
//!
//! let input = b"hashcrew";
//! let mut state = Xxh3_64::new();
//! io::copy(&mut input.as_slice(), &mut state).unwrap();
//!
//! assert_eq!(state.digest(), xxh3_64(input));
//! # }
//! ```
//!
//! # Complete and incremental hashing
//!
//! Hash a complete byte slice with a free function, or feed the same bytes to
//! a reusable state:
//!
//! ```
//! use hashcrew::xxhash::Xxh64;
//! use hashcrew::xxhash::xxh64;
//!
//! let expected = xxh64(b"hashcrew", 42);
//! let mut state = Xxh64::with_seed(42);
//! state.update(b"hash");
//! state.update(b"crew");
//!
//! assert_eq!(state.digest(), expected);
//! ```
extern crate std;
// Ported from Austin Appleby's public-domain MurmurHash3 finalizer:
// https://github.com/aappleby/smhasher/blob/07bb4de10a63e8cc2e1724865454eba635742383/src/MurmurHash3.cpp
// Derived from XXH3_mul128_fold64 in xxHash 0.8.3's xxhash.h:
// https://github.com/Cyan4973/xxHash/blob/e626a72bc2321cd320e953a0ccf1584cad60f363/xxhash.h
// Copyright (C) 2012-2023 Yann Collet. The derived portion remains BSD-2-Clause;
// Hashcrew's modifications are Apache-2.0. See LICENSE for the full upstream terms.