Нет одношагового решения для этого. Макрос include!
предполагает, что он загрузит полностью сформированный синтаксис Rust из файла, а ваш файл - не тот.
Самым близким является скрипт сборки . При этом вы можете анализировать любые входные данные и генерировать любые выходные данные.
Поскольку ваш код почти буквенный массив, самое дешевое, что вы можете сделать, это добавить квадратные скобки вокруг него:
build.rs
use std::{
env,
fs::File,
io::{self, Write},
path::PathBuf,
};
fn main() -> Result<(), Box<std::error::Error>> {
let mut src = File::open("file.in")?;
let out_dir: PathBuf = env::var_os("OUT_DIR").ok_or("Cannot find OUT_DIR")?.into();
let out_file = out_dir.join("file.in.rs");
let mut out = File::create(out_file)?;
write!(&mut out, "[")?;
io::copy(&mut src, &mut out)?;
write!(&mut out, "]")?;
Ok(())
}
Затем вы можете просто импортировать этот массив напрямую:
const STRINGS: &[&str] = &include!(concat!(env!("OUT_DIR"), "/file.in.rs"));
fn main() {
for s in STRINGS {
println!("{}", s);
}
}
Конечно, вы можете изменить скрипт сборки в соответствии со своими потребностями. Например, вы можете сгенерировать вызов вашего макроса и затем импортировать файл, содержащий вызов макроса.
Смотри также:
В качестве бонуса ваш макрос должен быть написан так, чтобы использовать в своих интересах vec!
, который использует некоторые внутренние компоненты компилятора для большей эффективности:
macro_rules! vec_strs {
($($element:expr),*) => {
vec![$($element.to_string()),*]
};
}