Hello!
I'm very new to Rust, so forgive me it's something simple (probably is).
I'm trying to use a HashMap (with a custom hasher) with a key type [u8; 40]. The compiler obviously tells me, that I could only use up to length 32, above that I would have to implement a lot of Traits.
How could I actually do this?
Thanks!
In current version of Rust arrays are very limited. It's going to be fixed eventually when const generics are aded.
You can pass a slice to a custom hasher. Instead of foo: [u8; 40]
pass &foo
, which will be a variable-length slice of &[u8]
, and it supports hash for any length.
For automatically derived traits use newtype instead of the raw array:
pub struct MyKey([u8; 40]);
impl Hash for MyKey {…a chunk of code goes here. you can reuse hash of slices…}
or
#[derive(Hash)]
pub struct MyKey([u8; 20], [u8; 20]);

2 Likes
You can also consider:
#[derive(Hash)]
struct Key([[u8; 20]; 2]);
And then use a bit of unsafe to reinterpret as [u8; 40]
when needed. That should be sound given array layout guarantees.
3 Likes
Thanks!
So just to be clear (it compiles, I'm just not sure it does what I think it does), this code should be fine for my needs? (I'm using MetroHashMap btw)
pub struct Key([u8; 40]);
impl Hash for Key {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl PartialEq for Key {
fn eq(&self, other: &Key) -> bool {
self.0[..] == other.0[..]
}
}
impl Eq for Key {}
Yeah, that should work - self.0.hash(state)
is using the blanket slice impl, if that's what you were wondering about.
1 Like