Создать неизменный HashMap из скрипта сборки Car go - PullRequest
2 голосов
/ 21 апреля 2020

Я использую что-то похожее на этот ответ , чтобы загрузить некоторые данные файла в двоичный файл Rust. Я хотел бы, чтобы эти данные были сохранены в HashMap, поэтому я могу искать по ключу в основной программе. Однако я не уверен, как это сделать так, чтобы эти данные были неизменными.

Из вектора, ранее определенного в build.rs, я предполагаю, что мог бы сделать что-то подобное в 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();
  // ...
}

Есть ли способ построить этот HashMap напрямую из build.rs и загрузить его в const in main.rs? Если я заменю подход вектор-кортеж, используемый в связанном ответе, на определение HashMap, повторяющееся с чем-то вроде data.insert(<key>,<value>);, могу ли я загрузить его в main.rs с include! таким же образом, сохранив неизменность HashMap?

Большое спасибо! Привет

1 Ответ

1 голос
/ 21 апреля 2020

Самый простой способ создать глобальную хэш-карту только для чтения - использовать 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.

Вы можете переместить эту логику c в код, сгенерированный build.rs, но было бы гораздо менее очевидно, что происходит.

...