2

I'm using something similar to this answer to load some file data into a Rust binary. I'd like this data to be stored in a HashMap, so I'm able to search by key in the main program. However, I'm not sure how to do it in a way that ensures this data is immutable.

From the vector previously defined in build.rs, I assume I could do something like this in main.rs:

const ALL_THE_FILES: &[(&str, &[u8])] = &include!(concat!(env!("OUT_DIR"), "/all_the_files.rs"));

fn main () {
  let all_the_files_hashmap: HashMap<&str, &[u8]> = ALL_THE_FILES.iter().cloned().collect();
  // ...
}

Is there any way to construct this HashMap directly from build.rs and load it to a const in main.rs? If I replace the tuple-vector approach used in the linked answer with a HashMap definition iterating with something like data.insert(<key>,<value>);, can I load this into main.rs with include! in the same way, keeping the HashMap immutable?

Thanks a lot! Regards

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
DavSanchez
  • 831
  • 8
  • 13

1 Answers1

1

The easiest way to create a global read-only hashmap is to use lazy_static:

#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

const ALL_THE_FILES: &[(&str, &[u8])] = ...;

lazy_static! {
    static ref FILE_TO_DATA: HashMap<&'static str, &'static [u8]> = {
        let mut m = HashMap::new();
        for (file, data) in ALL_THE_FILES {
            m.insert(*file, *data);
        }
        m
    };
}

fn main() {
    println!("{:?}", FILE_TO_DATA.get("foo").unwrap());
}

Playground.

You could move this logic into code generated by build.rs, but it would be much less obvious what's going on.

kreo
  • 2,613
  • 2
  • 19
  • 31