我想将整个目录复制到用户$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
必须是字符串文字。
据我所知,有两种选择:
这样做的最佳方式是什么?
答案 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
。