-
Notifications
You must be signed in to change notification settings - Fork 371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement Hasher
trait for Hasher
#87
Conversation
(Just dropping in to make a general apology for not being responsive this week. I'm ramping up at a new job. I will probably need to get to this PR over the weekend.) |
Could you say more about the use case here? One of my worries is that |
When I was looking through the documentation I found the This trait makes it possible to hash any type implementing use std::hash::Hash;
use std::hash::Hasher as _;
use blake3::Hasher;
#[derive(Hash)]
pub struct Example {
pub field_0: String,
pub field_1: usize,
}
fn main() {
let example = Example {
field_0: "Hello".into(),
field_1: 123,
};
let mut hasher = Hasher::new();
// this does only work when the `Hasher` trait is implemented for `Hasher`
example.hash(&mut hasher);
let hash = hasher.finish();
assert_eq!(11927595719148982277, hash);
} Sometimes it isn't even possible to convert a struct to bytes, in which case only the
By using use std::collections::HashMap;
use blake3::Hasher;
let mut map = HashMap::new();
map.insert(Hasher::new(), 0_usize); (this is not possible, because It is possible to use the use std::collections::HashMap;
use std::hash::BuildHasher;
/// This is a custom type implementing the `BuildHasher` trait,
/// which is required by `HashMap::with_hasher`
struct Blake3HasherBuilder;
impl BuildHasher for Blake3HasherBuilder {
// NOTE: this only works if blake3::Hasher implements the `Hasher` trait
type Hasher = blake3::Hasher;
fn build_hasher(&self) -> Self::Hasher { blake3::Hasher::new() }
}
let mut map = HashMap::with_hasher(hash_builder);
map.insert("hello", "world"); // the "hello" key would be hashed with blake3::Hasher instead of the `DefaultHasher`
I think you might have confused the
|
I definitely did! I need to reread this from the beginning. |
|
Now that I understand better what's going on here, my biggest reservation is that
Coincidentally, we've been thinking a lot about this exact problem at work. Uncanny timing! I think the problem of hashing structured data is really interesting and useful but also really subtle. (There must be rigorous papers on this, but I don't know of any. If anyone reading along can link to research, please do.) My tldr on this is that I think there are some commonly expected properties that the Rust standard library's approach is missing, so "do what the Rust standard library does" is unlikely to be a good solution. Diving into that, here are some example questions:
That very last question in particular, about whether new fields can be added in a backwards-compatible way, is a central design goal of Protobuf and a very useful property of many other serialization formats like JSON and MessagePack. I think that an Industrial Strength™ design for hashing structured data will need to take a position on this, and I think users are likely to need to know the details of that position and design around them. |
In RustCrypto we had the following discussions about hashing structures some time ago: |
https://doc.rust-lang.org/std/hash/trait.Hasher.html