我之前曾问过How can I include an arbitrary set of Protobuf-built files without knowing their names? - 这是一个基于结果的跟进问题。
我现在有一个我包含的文件,它包含各自不同的模块 - 即:
mod foo;
mod bar;
这些模块及其名称可以完全随机,具体取决于用户放置在原型文件目录中的内容。
我需要对这些随机模块执行操作。例如,我想要做的第一件事是获取这些新模块中存在的所有消息,并将它们作为字符串呈现给我可以推送到矢量。
真的是一个2部分的问题:
FileDescriptorProto()
方法,查看Google protobuf文档,看起来与此类似:Google Protobuf FileDescriptor 答案 0 :(得分:1)
如果包含由build.rs
脚本生成的单个文件,该怎么办?该脚本可以扫描给定目录并生成正确的文件。
我有一个可以链接到的示例,但它包含Project Euler解决方案的解决方案,因此我不确定人们对此的看法。
以下是我使用的build.rs
:
// Generate the problem list based on available modules.
use std::env;
use std::fs;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use regex::Regex;
extern crate regex;
fn main() {
let odir = env::var("OUT_DIR").unwrap();
let cwd = env::current_dir().unwrap().to_str().unwrap().to_owned();
let dst = Path::new(&odir);
let gen_name = dst.join("plist.rs");
let mut f = File::create(&gen_name).unwrap();
writeln!(&mut f, "// Auto-generated, do not edit.").unwrap();
writeln!(&mut f, "").unwrap();
writeln!(&mut f, "pub use super::Problem;").unwrap();
writeln!(&mut f, "").unwrap();
let problems = get_problems();
// Generate the inputs.
for &p in problems.iter() {
writeln!(&mut f, "#[path=\"{1}/src/pr{0:03}.rs\"] mod pr{0:03};", p, cwd).unwrap();
}
writeln!(&mut f, "").unwrap();
// Make the problem set.
writeln!(&mut f, "pub fn make() -> Vec<Box<Problem + 'static>> {{").unwrap();
writeln!(&mut f, " let mut probs = Vec::new();").unwrap();
for &p in problems.iter() {
writeln!(&mut f, " add_problem!(probs, pr{:03}::Solution);", p).unwrap();
}
writeln!(&mut f, " probs").unwrap();
writeln!(&mut f, "}}").unwrap();
drop(f);
}
// Get all of the problems, based on standard filenames of "src/prxxx.rs" where xxx is the problem
// number. Returns the result, sorted.
fn get_problems() -> Vec<u32> {
let mut result = vec![];
let re = Regex::new(r"^.*/pr(\d\d\d)\.rs$").unwrap();
for entry in fs::read_dir(&Path::new("src")).unwrap() {
let entry = entry.unwrap();
let p = entry.path();
let n = p.as_os_str().to_str();
let name = match n {
Some(n) => n,
None => continue,
};
match re.captures(name) {
None => continue,
Some(cap) => {
let num: u32 = cap.at(1).unwrap().parse().unwrap();
result.push(num);
},
}
}
result.sort();
result
}
src
下的另一个源文件具有以下内容:
include!(concat!(env!("OUT_DIR"), "/plist.rs"));
答案 1 :(得分:0)
根据@ Shepmaster在原帖中评论中的建议,我找到了一种方法:
由于Rust不支持反射(在本文发布时),我不得不扩展我的货物构建脚本,以便在生成的文件中编写代码,以便我知道这些符号始终存在。
我为我所包含的每个模块生成了特定的函数(因为我在那时拥有了它们的模块名称),然后生成了具有通用名称的“聚合”函数,我可以在我的主代码中调用它们。