Search code examples
rustborrowingcopy-on-writerun-time-polymorphism

A Hashmap supporting String and &str


How do I define a HashMap supporting both String and &str in its key and content? I tried the following:

fn mapping<T: Into<String>>() -> HashMap<T, T> {
  let mut map: HashMap<T, T> = HashMap::new();
  map.insert("first_name", "MyFirstName");
  map.insert("last_name".to_string(), "MyLastName".to_string());
  map
}

fn main() {
  let mut mapping = mapping();
}

But it doesn't compile, saying:

error[E0599]: no method named `insert` found for type `std::collections::HashMap<T, T>` in the current scope
error[E0277]: the trait bound `T: std::cmp::Eq` is not satisfied
error[E0277]: the trait bound `T: std::hash::Hash` is not satisfied

Solution

  • The built-in way to abstract over whether data is borrowed or owned is Cow.

    use std::borrow::Cow;
    use std::collections::HashMap;
    
    fn mapping() -> HashMap<Cow<'static, str>, Cow<'static, str>> {
        let mut map = HashMap::new();
        map.insert("first_name".into(), "MyFirstName".into());
        map.insert("last_name".to_string().into(), "MyLastName".to_string().into());
        map
    }
    

    Both &str and String can be converted to a Cow<str> using .into().