Как я могу использовать макрос включения для загрузки нескольких элементов из одного файла? - PullRequest
0 голосов
/ 13 июня 2019
macro_rules! vec_strs {
    (
        $($element:expr),*
    ) => {
        {
            let mut v = Vec::new();
            $(
                v.push(format!("{}", $element));
            )*
            v
        }
    };
}

fn main() {
    let v = vec_strs!("1", "2");
    println!("{}", v);
}

Проблема в том, что мои строки помещены в файл:

file.in:

"first", "second", "third", .... 

Я не могу изменить содержимоефайл.Как я могу использовать include! / include_str! с моим макросом vec_strs для «загрузки» элементов в вектор из file.in?Заранее спасибо.

1 Ответ

0 голосов
/ 14 июня 2019

Нет одношагового решения для этого. Макрос 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()),*]
    };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...