Crate hash_with

Crate hash_with 

Source
Expand description

§HashWith

HashWith is a procedural macro for deriving Hash on structs that contain fields which do not implement Hash by default (like f64). It supports custom hash functions per field.

§Inline Example

The #[hash_with(expr)] notation takes in some expression and so long as the result is a type that implements Hash. For example if you wanted to serialize a f64 in your struct you can use the following snippet.

use hash_with::HashWith;

/// Some struct which needs to implement [`Hash`]
#[derive(HashWith)]
struct Brightness {
    /// The inner value with a hash function override.
    /// The `f64::to_bits()` method returns a `u64` which is why it can be used here.
    #[hash_with(self.inner.to_bits())]
    inner: f64,
}

// Sets values
let b1 = Brightness { inner: 1.1 };
let b2 = Brightness { inner: 2.2 };

// Not equal in terms of their hash
assert_ne!(b1.get_hash(), b2.get_hash());

§Function Call Example

With HashWith you can also call functions by name for the Hash implementation. This can be useful for repeatedly creating a Hash implementation for multiple of the same datatype in a struct.

The function must however have the signature Fn<T, H: std::hash::Hasher>(T, &mut H) -> (). Basically what this means is the function must look something like the following example.

/// A custom hash function for f64
fn hash_f64_bits<H: std::hash::Hasher>(val: &f64, state: &mut H) {
    val.to_bits().hash(state);
}

/// An example struct.
#[derive(HashWith)]
struct Config {
    name: String,
    /// A brightness value which is hashed with [`hash_f64_bits`].
    #[hash_with = "hash_f64_bits"]
    brightness: f64,
}

§Ignoring Fields in Hash Calculation Example

The #[hash_without] attribute can be applied to struct fields to exclude them from the generated hash. This is useful for fields that should not affect equality in hashed collections or when you want to ignore volatile or irrelevant data.

#[derive(HashWith)]
struct User {
    id: u32,
    /// This field will be ignored in the hash calculation.
    #[hash_without]
    session_token: String,
}

let user_1 = User { id: 1, session_token: "abc".into() };
let user_2 = User { id: 1, session_token: "xyz".into() };

// The hash ignores `session_token`, so these are equal in terms of hash.
assert_eq!(user_1.get_hash(), user_2.get_hash());

Derive Macros§

HashWith
Derives Hash implementations for the attributes of struct, using custom per-field hash functions when needed.