fnv1a32 function
Computes a deterministic 32-bit FNV-1a hash over input.
FNV-1a (Fowler–Noll–Vo 1a) is a lightweight, non-cryptographic hash algorithm optimized for fast execution and high dispersion over arbitrary strings.
Determinism across SSR and Web Platforms
In Bloom JS Native, fnv1a32 is the mathematical foundation for Scoped CSS.
Server-Side Rendering (running on the Dart VM) and browser client DOM mounting
(compiled to JavaScript via dart2js or WebAssembly via dart2wasm) MUST compute
bit-for-bit identical hashes for identical stylesheet inputs. If hashing diverged
between 64-bit VM integers and JavaScript 32-bit bitwise semantics, class names
emitted during SSR (renderToHtml) would not match those generated during client
hydration (mount), causing broken CSS styling and hydration mismatches.
This implementation guarantees identical output across all runtimes by explicitly
masking all bitwise shifts, additions, and XOR operations with 0xFFFFFFFF across
both the low and high bytes of each character code unit.
Used internally by ScopedCss.compile and scopedCss to derive 7-character hex suffixes.
final hash = fnv1a32('.card { color: #6366f1; }');
final hex = hash.toRadixString(16).padLeft(8, '0').substring(0, 7);
print('Scoped hash: $hex');
Implementation
int fnv1a32(String input) {
var hash = 0x811c9dc5;
for (var i = 0; i < input.length; i++) {
final code = input.codeUnitAt(i);
hash ^= (code & 0xFF);
// 32-bit multiplication by FNV prime 16777619 (0x01000193) via bitwise shifts:
// 16777619 = 1 + (1<<1) + (1<<4) + (1<<7) + (1<<8) + (1<<24)
hash = (hash +
(hash << 1) +
(hash << 4) +
(hash << 7) +
(hash << 8) +
(hash << 24)) &
0xFFFFFFFF;
final high = code >> 8;
if (high != 0) {
hash ^= (high & 0xFF);
hash = (hash +
(hash << 1) +
(hash << 4) +
(hash << 7) +
(hash << 8) +
(hash << 24)) &
0xFFFFFFFF;
}
}
return hash & 0xFFFFFFFF;
}