protoc_gen_prost_serde/
lib.rs1#![doc = include_str!("../README.md")]
2
3use std::str;
4
5use prost::Message;
6use prost_types::compiler::CodeGeneratorRequest;
7use protoc_gen_prost::{Generator, InvalidParameter, ModuleRequestSet, Param, Params};
8
9use self::generator::PbJsonGenerator;
10
11mod generator;
12
13pub fn execute(raw_request: &[u8]) -> protoc_gen_prost::Result {
15 let request = CodeGeneratorRequest::decode(raw_request)?;
16 let params = request.parameter().parse::<Parameters>()?;
17
18 let mut builder = params.to_pbjson_builder();
19 for file in &request.proto_file {
20 builder.register_file_descriptor(file.clone());
21 }
22
23 let module_request_set = ModuleRequestSet::new(
24 request.file_to_generate,
25 request.proto_file,
26 raw_request,
27 params.default_package_filename.as_deref(),
28 params.flat_output_dir,
29 )?;
30
31 let files = PbJsonGenerator::new(builder, !params.no_include).generate(&module_request_set)?;
32
33 Ok(files)
34}
35
36#[derive(Debug, Default)]
40struct Parameters {
41 default_package_filename: Option<String>,
42 extern_path: Vec<(String, String)>,
43 retain_enum_prefix: bool,
44 preserve_proto_field_names: bool,
45 ignore_unknown_fields: bool,
46 emit_fields: bool,
47 use_integers_for_enums: bool,
48 no_include: bool,
49 btree_map: Vec<String>,
50 flat_output_dir: bool,
51 exclude: Vec<String>,
52}
53
54impl Parameters {
55 fn to_pbjson_builder(&self) -> pbjson_build::Builder {
56 let mut builder = pbjson_build::Builder::new();
57
58 for (proto_path, rust_path) in &self.extern_path {
59 builder.extern_path(proto_path, rust_path);
60 }
61
62 if self.retain_enum_prefix {
63 builder.retain_enum_prefix();
64 }
65
66 if self.preserve_proto_field_names {
67 builder.preserve_proto_field_names();
68 }
69
70 if self.ignore_unknown_fields {
71 builder.ignore_unknown_fields();
72 }
73
74 if self.emit_fields {
75 builder.emit_fields();
76 }
77
78 if self.use_integers_for_enums {
79 builder.use_integers_for_enums();
80 }
81
82 if !self.btree_map.is_empty() {
83 builder.btree_map(self.btree_map.clone());
84 }
85
86 builder.btree_map(self.btree_map.clone());
87
88 if !self.exclude.is_empty() {
89 builder.exclude(self.exclude.clone());
90 }
91
92 builder
93 }
94}
95
96impl str::FromStr for Parameters {
97 type Err = InvalidParameter;
98 fn from_str(s: &str) -> Result<Self, Self::Err> {
99 let mut ret_val = Self::default();
100 for param in Params::from_protoc_plugin_opts(s)? {
101 match param {
102 Param::Parameter {
103 param: "default_package_filename",
104 }
105 | Param::Value {
106 param: "default_package_filename",
107 ..
108 } => ret_val.default_package_filename = param.value().map(|s| s.into_owned()),
109 Param::Parameter {
110 param: "retain_enum_prefix",
111 }
112 | Param::Value {
113 param: "retain_enum_prefix",
114 value: "true",
115 } => ret_val.retain_enum_prefix = true,
116 Param::Value {
117 param: "retain_enum_prefix",
118 value: "false",
119 } => (),
120 Param::Parameter {
121 param: "preserve_proto_field_names",
122 }
123 | Param::Value {
124 param: "preserve_proto_field_names",
125 value: "true",
126 } => ret_val.preserve_proto_field_names = true,
127 Param::Value {
128 param: "preserve_proto_field_names",
129 value: "false",
130 } => (),
131 Param::Parameter {
132 param: "ignore_unknown_fields",
133 }
134 | Param::Value {
135 param: "ignore_unknown_fields",
136 value: "true",
137 } => ret_val.ignore_unknown_fields = true,
138 Param::Parameter {
139 param: "emit_fields",
140 }
141 | Param::Value {
142 param: "emit_fields",
143 value: "true",
144 } => ret_val.emit_fields = true,
145 Param::Parameter {
146 param: "use_integers_for_enums",
147 }
148 | Param::Value {
149 param: "use_integers_for_enums",
150 value: "true",
151 } => ret_val.use_integers_for_enums = true,
152 Param::Parameter {
153 param: "no_include",
154 }
155 | Param::Value {
156 param: "no_include",
157 value: "true",
158 } => ret_val.no_include = true,
159 Param::Value {
160 param: "no_include",
161 value: "false",
162 } => (),
163 Param::KeyValue {
164 param: "extern_path",
165 key: prefix,
166 value: module,
167 } => ret_val.extern_path.push((prefix.to_string(), module)),
168 Param::Value {
169 param: "btree_map",
170 value,
171 } => ret_val.btree_map.push(value.to_string()),
172 Param::Parameter {
173 param: "flat_output_dir",
174 }
175 | Param::Value {
176 param: "flat_output_dir",
177 value: "true",
178 } => ret_val.flat_output_dir = true,
179 Param::Value {
180 param: "flat_output_dir",
181 value: "false",
182 } => (),
183 Param::Value {
184 param: "exclude",
185 value: prefix,
186 } => ret_val.exclude.push(prefix.to_string()),
187 _ => return Err(InvalidParameter::from(param)),
188 }
189 }
190
191 Ok(ret_val)
192 }
193}