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 exactly the collections the unordered field types require, 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.