The Borrow trait and structs as HashMap keys

I have the following struct

#[derive(Debug, Hash)]
struct CustomKey {
    field1: String,
    field2: String
}

, but I want to be able to write a function like

fn get(field1: &str, field2: &str, set: HashMap<CustomKey, AType>) -> AType

without having to copy the strings into a new CustomKey struct.

I've been playing around with something like

struct CustomKeyRef<'a> {
    field1: &'a str,
    field2: &'a str
}

and impl<'a> Borrow<CustomKey> for CustomKeyRef<'a>, but I can't seem to get it to work. Is this the right approach?

EDIT
I guess my problem is that I don't need the Strings to exist after I have hashed them, whereas I assume the HashSet/Map stores the keys so you can recover them. Is there an alternative data structure that doesn't store the keys, and so is missing methods like .keys(), but still has things like .get()?

1 Like

If you can change CustomKey to:

struct CustomKey<'a> {
   field1: Cow<'a, str>,
   field2: Cow<'a, str>,
}

then you can create a temp CustomKey cheaply for the lookup.

Another option is to use the indexmap crate instead, which has its own Equivalent trait that makes this possible: indexmap::map::IndexMap - Rust

This situation is a known shortcoming of the Borrow trait.

4 Likes

Great answer thankyou!