refactor(ui/preset): drop AsU32ForHash trait, tighten Custom-hash doc

The trait had one impl (BloomQuality) while DiskQuality/AaQuality were
hashed inline — it abstracted nothing. Call BloomQuality::levels()
directly so the three hash lines read as parallel conversions. Hash
output is unchanged (as_u32_ just delegated to levels()).

Also fix the canonical_hash(Custom) doc: it claimed 'by construction'
but the 0-sentinel guarantee actually comes from ui_system's
matches!(Cinematic|Performance|Web) arm excluding Custom from the
comparison, not from SipHash avoiding 0.
This commit is contained in:
xfy 2026-07-17 15:36:07 +08:00
parent 3bf1f1ac83
commit 3a8a1ee1c3

View File

@ -52,8 +52,10 @@ pub fn apply(p: Preset, params: &mut BlackHoleParams) {
}
}
/// Stable hash of a preset's canonical bundle. `Custom` returns 0 (it never
/// matches any real params state, by construction — see `hashed_fields`).
/// Stable hash of a preset's canonical bundle. `Custom` returns 0.
/// (The Custom case is never fed to a `canonical_hash == params_hash`
/// comparison: `ui_system`'s preset-detection arm only checks
/// Cinematic | Performance | Web, so the 0 sentinel never risks matching.)
pub fn canonical_hash(p: Preset) -> u64 {
match bundle(p) {
Some(b) => b.hash(),
@ -90,14 +92,9 @@ impl HashedParams {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
self.steps.hash(&mut hasher);
self.render_scale.to_bits().hash(&mut hasher); // f32: hash bit pattern, not value
self.bloom_quality.as_u32_().hash(&mut hasher);
self.bloom_quality.levels().hash(&mut hasher);
self.disk_quality.as_u32().hash(&mut hasher);
self.aa_quality.samples().hash(&mut hasher);
hasher.finish()
}
}
// Local trait adapters: BloomQuality has levels(), DiskQuality has as_u32(),
// AaQuality has samples(). Unify under one name for hashing.
trait AsU32ForHash { fn as_u32_(self) -> u32; }
impl AsU32ForHash for BloomQuality { fn as_u32_(self) -> u32 { self.levels() } }