我如何使用include_str!多个文件或整个目录?

时间:2018-05-27 14:52:51

标签: rust

我想将整个目录复制到用户$HOME中的某个位置。单独将文件复制到该目录非常简单:

let contents = include_str!("resources/profiles/default.json");
let fpath = dpath.join(&fname);
fs::write(fpath, contents).expect(&format!("failed to create profile: {}", n));

我还没有办法让它适应多个文件:

for n in ["default"] {
    let fname = format!("{}{}", n, ".json");
    let x = format!("resources/profiles/{}", fname).as_str();
    let contents = include_str!(x);
    let fpath = dpath.join(&fname);
    fs::write(fpath, contents).expect(&format!("failed to create profile: {}", n));
}

...编译器抱怨x必须是字符串文字。

据我所知,有两种选择:

  1. 编写自定义宏。
  2. 为我要复制的每个文件复制第一个代码。
  3. 这样做的最佳方式是什么?

2 个答案:

答案 0 :(得分:4)

我会创建a build script遍历目录,构建包含名称的元组数组和另一个宏调用以包含原始数据:

pos

这有一些缺点,即它要求路径可以表达为use std::{ env, error::Error, fs::{self, File}, io::Write, path::Path, }; const SOURCE_DIR: &str = "some/path/to/include"; fn main() -> Result<(), Box<Error>> { let out_dir = env::var("OUT_DIR")?; let dest_path = Path::new(&out_dir).join("all_the_files.rs"); let mut all_the_files = File::create(&dest_path)?; writeln!(&mut all_the_files, r#"["#,)?; for f in fs::read_dir(SOURCE_DIR)? { let f = f?; if !f.file_type()?.is_file() { continue; } writeln!( &mut all_the_files, r#"("{name}", include_bytes!("{name}")),"#, name = f.path().display(), )?; } writeln!(&mut all_the_files, r#"];"#,)?; Ok(()) } 。由于您已经在使用&str,因此我认为这不是额外的要求。

由于我们包含文件,因此我使用include_string!代替include_bytes!,但如果您真的需要,可以切换回来。原始字节跳过在编译时执行UTF-8验证,因此它是一个小小的胜利。

使用它涉及导入生成的值:

include_str!

答案 1 :(得分:0)

使用宏:

macro_rules! incl_profiles {
    ( $( $x:expr ),* ) => {
        {
            let mut profs = Vec::new();
            $(
                profs.push(($x, include_str!(concat!("resources/profiles/", $x, ".json"))));
            )*

            profs
        }
    };
}

...

let prof_tups: Vec<(&str, &str)> = incl_profiles!("default", "python");

for (prof_name, prof_str) in prof_tups {
    let fname = format!("{}{}", prof_name, ".json");
    let fpath = dpath.join(&fname);
    fs::write(fpath, prof_str).expect(&format!("failed to create profile: {}", prof_name));
}

注意:这不是动态的。文件(“default”和“python”)在宏的调用中指定。

已更新:使用Vec代替HashMap