1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::collections::HashSet;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::path::Path;
use std::path::PathBuf;
use anyhow::Context;
use protobuf::descriptor::FileDescriptorSet;
use crate::protoc;
use crate::pure;
use crate::which_parser::WhichParser;
use crate::ParsedAndTypechecked;
#[derive(Default, Debug)]
pub struct Parser {
which_parser: WhichParser,
pub(crate) includes: Vec<PathBuf>,
pub(crate) inputs: Vec<PathBuf>,
pub(crate) protoc: Option<PathBuf>,
pub(crate) protoc_extra_args: Vec<OsString>,
pub(crate) capture_stderr: bool,
}
impl Parser {
pub fn new() -> Parser {
Parser::default()
}
pub fn pure(&mut self) -> &mut Self {
self.which_parser = WhichParser::Pure;
self
}
pub fn protoc(&mut self) -> &mut Self {
self.which_parser = WhichParser::Protoc;
self
}
pub fn include(&mut self, include: impl AsRef<Path>) -> &mut Self {
self.includes.push(include.as_ref().to_owned());
self
}
pub fn includes(&mut self, includes: impl IntoIterator<Item = impl AsRef<Path>>) -> &mut Self {
for include in includes {
self.include(include);
}
self
}
pub fn input(&mut self, input: impl AsRef<Path>) -> &mut Self {
self.inputs.push(input.as_ref().to_owned());
self
}
pub fn inputs(&mut self, inputs: impl IntoIterator<Item = impl AsRef<Path>>) -> &mut Self {
for input in inputs {
self.input(input);
}
self
}
pub fn protoc_path(&mut self, protoc: &Path) -> &mut Self {
self.protoc = Some(protoc.to_owned());
self
}
pub fn protoc_extra_args(
&mut self,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
) -> &mut Self {
self.protoc_extra_args = args.into_iter().map(|s| s.as_ref().to_owned()).collect();
self
}
pub fn capture_stderr(&mut self) -> &mut Self {
self.capture_stderr = true;
self
}
pub fn parse_and_typecheck(&self) -> anyhow::Result<ParsedAndTypechecked> {
match &self.which_parser {
WhichParser::Pure => {
pure::parse_and_typecheck::parse_and_typecheck(&self).context("using pure parser")
}
WhichParser::Protoc => protoc::parse_and_typecheck::parse_and_typecheck(&self)
.context("using protoc parser"),
}
}
pub fn file_descriptor_set(&self) -> anyhow::Result<FileDescriptorSet> {
let mut generated = self.parse_and_typecheck()?;
let relative_paths: HashSet<_> = generated
.relative_paths
.iter()
.map(|path| path.to_string())
.collect();
generated
.file_descriptors
.retain(|fd| relative_paths.contains(fd.name()));
let mut fds = FileDescriptorSet::new();
fds.file = generated.file_descriptors;
Ok(fds)
}
}