There is no one-step solution to this. The include!
macro assumes that it will load fully-formed Rust syntax from a file and your file is not that.
The closest thing is a build script. With this, you can parse any kind of input and generate any kind of output.
Since your code is almost a literal array, the cheapest thing you can do is to add square brackets around it:
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(())
}
You can then just import that array directly:
const STRINGS: &[&str] = &include!(concat!(env!("OUT_DIR"), "/file.in.rs"));
fn main() {
for s in STRINGS {
println!("{}", s);
}
}
You can, of course, change the build script to suit your needs. For example, you could generate a call to your macro and then import the file containing the macro call.
See also:
As a bonus, your macro should be written to take advantage of vec!
, which uses some compiler internals to be more efficient:
macro_rules! vec_strs {
($($element:expr),*) => {
vec![$($element.to_string()),*]
};
}