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