Skip to main content

key_paths_core/
field_diff.rs

1//! Per-field change detection without cloning whole state trees.
2
3use core::hash::{Hash, Hasher};
4
5/// FNV-1a 64-bit hasher (no `std` required).
6struct FnvHasher(u64);
7
8impl Hasher for FnvHasher {
9    fn finish(&self) -> u64 {
10        self.0
11    }
12
13    fn write(&mut self, bytes: &[u8]) {
14        for b in bytes {
15            self.0 ^= *b as u64;
16            self.0 = self.0.wrapping_mul(0x100000001b3);
17        }
18    }
19}
20
21/// Hash any [`Hash`] value without cloning it.
22pub fn hash_value<T: Hash + ?Sized>(value: &T) -> u64 {
23    let mut h = FnvHasher(0xcbf29ce484222325);
24    value.hash(&mut h);
25    h.finish()
26}
27
28/// State types implement this so subscribers can detect which fields changed
29/// by comparing per-field hashes — never by cloning the whole value.
30pub trait FieldDiff: Hash {
31    /// Stable identifier for a top-level (or nested) field path.
32    type Path: Copy + Eq + Hash + Send + Sync + 'static;
33
34    /// Push `(path, field_hash)` for each tracked field.
35    fn field_hashes(&self, out: &mut alloc::vec::Vec<(Self::Path, u64)>);
36}