1

I have several pieces of state that I want to store inside respective hashmaps. Something that looks like this:

let mut directory_hash: HashMap<String, String> = HashMap::new();
let mut component_hash: HashMap<String, String> = HashMap::new();
let mut directive_hash: HashMap<String, String> = HashMap::new();

I want all of these slices to be held inside one app_state object, and I'll initialize it similar to this:

pub fn init_app_state() -> HashMap<&'static str, HashMap<String, String>> {
    let mut directory_hash: HashMap<String, String> = HashMap::new();
    let mut component_hash: HashMap<String, String> = HashMap::new();
    let mut directive_hash: HashMap<String, String> = HashMap::new();

    let mut tree_state: HashMap<&str, HashMap<String, String>> = HashMap::new();
    tree_state.insert("directory_hash", directory_hash);
    tree_state.insert("component_hash", component_hash);
    tree_state.insert("module_hash", module_hash);

    tree_state
}

let mut app_state = state::app_state::init_app_state();

Now let's say I want to insert into one of the nested hashmaps. How can I do this?

Here's a snippet of a few non-working examples:

  1. let mut app_state = state::app_state::init_app_state();
    let mut dir_hash = &mut app_state["directory_hash"];
    dir_hash.insert(String::from("1"), String::from("first entry"));
    

    The error above is on the second line (app_state["directory_hash"])

    cannot borrow data in an index of `std::collections::HashMap<&str, std::collections::HashMap<std::string::String, std::string::String>>` as mutable
    
    cannot borrow as mutable
    
    help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::collections::HashMap<std::string::String, std::string::String>>`rustc(E0596)
    
  2. let mut app_state = state::app_state::init_app_state();
    let mut dir_hash = &mut app_state.entry("directory_hash");
    dir_hash.insert(String::from("1"), String::from("first entry"));
    

    The error here is on line 3 (dir_hash.insert(.....))

    use of unstable library feature 'entry_insert'
    
    note: see issue #65225 <https://github.com/rust-lang/rust/issues/65225> for more information
    

    I've looked at the entry API but I'm not sure if this is the approach to take.

How can I update this nested bit of state?

I will probably change each of these HashMap instances to a property on a State struct. But I am still curious about how the approach above works in Rust.

Here is the approach I am currently taking:

pub struct State {
    pub directory_hash: HashMap<String, String>,
    pub component_hash: HashMap<String, String>,
    pub module_hash: HashMap<String, String>,
}

impl State {
    pub fn new() -> State {
        let directory_hash: HashMap<String, String> = HashMap::new();
        let component_hash: HashMap<String, String> = HashMap::new();
        let module_hash: HashMap<String, String> = HashMap::new();

        State {
            directory_hash,
            component_hash,
            module_hash,
        }
    }
}


let app_state = state::app_state::State::new();
let mut dir_hash = app_state.directory_hash;
dir_hash.insert(String::from("1"), String::from("first value!"));
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Hanzy
  • 394
  • 4
  • 17

1 Answers1

1

As the error message says, HashMap doesn't implement IndexMut. Use get_mut to get an Option<&mut V>:

let mut app_state = state::app_state::init_app_state();
let dir_hash = app_state.get_mut("directory_hash").unwrap();
dir_hash.insert(String::from("1"), String::from("first entry"));

(Playground)

John Kugelman
  • 349,597
  • 67
  • 533
  • 578