Skip to main content

Module fingerprint

Module fingerprint 

Source
Expand description

Stable content hashing, so a receiver can check that a delta is being applied to the state it was computed against.

std::hash::Hash cannot do this job for two reasons. It is not implemented for HashSet or HashMap, which are important collections for the unordered field type, and the hash it feeds a DefaultHasher is explicitly allowed to change between Rust releases — fine for a hash table that lives and dies in one process, useless for a value two processes have to agree on.

Fingerprint fixes both. Sets and maps are folded commutatively so iteration order cannot matter, and Hasher is FNV-1a with the constants written down here, so the same value fingerprints identically on any platform, any Rust version, forever.

Derive it rather than writing it:

use delta_struct::{fingerprint_of, Fingerprint};
use std::collections::HashSet;

#[derive(Fingerprint)]
struct Device {
    services: HashSet<String>,
    online: bool,
}

let device = |online| Device {
    services: vec!["ssh".to_string(), "http".to_string()].into_iter().collect(),
    online,
};

// Set iteration order does not reach the fingerprint.
assert_eq!(fingerprint_of(&device(true)), fingerprint_of(&device(true)));
assert_ne!(fingerprint_of(&device(true)), fingerprint_of(&device(false)));

Structs§

Hasher
The hasher Fingerprint writes into: FNV-1a, 64-bit.

Traits§

Fingerprint
A value whose contents can be reduced to a number that two processes will agree on.

Functions§

fingerprint_of
Fingerprints a value on its own, which is what you usually want.