Skip to main content

protoc_gen_prost_utoipa/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::str;
4
5use prost::Message;
6use prost_types::{compiler::CodeGeneratorRequest, FileDescriptorSet};
7use protoc_gen_prost::{Generator, InvalidParameter, ModuleRequestSet, Param, Params};
8
9use self::generator::PrutoipaGenerator;
10
11mod generator;
12
13/// Execute the core _Prost!_ generator from a raw [`CodeGeneratorRequest`]
14pub 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 file_descriptor_set = FileDescriptorSet { file: Vec::new() };
19    for file in &request.proto_file {
20        file_descriptor_set.file.push(file.clone());
21    }
22
23    let mut builder = prutoipa_build::Builder::new();
24    builder.register_descriptors(file_descriptor_set)?;
25
26    let module_request_set = ModuleRequestSet::new(
27        request.file_to_generate,
28        request.proto_file,
29        raw_request,
30        params.default_package_filename.as_deref(),
31    )?;
32
33    let files =
34        PrutoipaGenerator::new(builder, !params.no_include).generate(&module_request_set)?;
35
36    Ok(files)
37}
38
39/// Parameters use to configure [`Generator`]s built into `protoc-gen-prost-utoipa`
40///
41/// [`Generator`]: protoc_gen_prost::generators::Generator
42#[derive(Debug, Default)]
43struct Parameters {
44    default_package_filename: Option<String>,
45    extern_path: Vec<(String, String)>,
46    retain_enum_prefix: bool,
47    preserve_proto_field_names: bool,
48    ignore_unknown_fields: bool,
49    emit_fields: bool,
50    use_integers_for_enums: bool,
51    no_include: bool,
52}
53
54impl str::FromStr for Parameters {
55    type Err = InvalidParameter;
56    fn from_str(s: &str) -> Result<Self, Self::Err> {
57        let mut ret_val = Self::default();
58        for param in Params::from_protoc_plugin_opts(s)? {
59            match param {
60                Param::Parameter {
61                    param: "default_package_filename",
62                }
63                | Param::Value {
64                    param: "default_package_filename",
65                    ..
66                } => ret_val.default_package_filename = param.value().map(|s| s.into_owned()),
67                Param::Parameter {
68                    param: "retain_enum_prefix",
69                }
70                | Param::Value {
71                    param: "retain_enum_prefix",
72                    value: "true",
73                } => ret_val.retain_enum_prefix = true,
74                Param::Value {
75                    param: "retain_enum_prefix",
76                    value: "false",
77                } => (),
78                Param::Parameter {
79                    param: "preserve_proto_field_names",
80                }
81                | Param::Value {
82                    param: "preserve_proto_field_names",
83                    value: "true",
84                } => ret_val.preserve_proto_field_names = true,
85                Param::Value {
86                    param: "preserve_proto_field_names",
87                    value: "false",
88                } => (),
89                Param::Parameter {
90                    param: "ignore_unknown_fields",
91                }
92                | Param::Value {
93                    param: "ignore_unknown_fields",
94                    value: "true",
95                } => ret_val.ignore_unknown_fields = true,
96                Param::Parameter {
97                    param: "emit_fields",
98                }
99                | Param::Value {
100                    param: "emit_fields",
101                    value: "true",
102                } => ret_val.emit_fields = true,
103                Param::Parameter {
104                    param: "use_integers_for_enums",
105                }
106                | Param::Value {
107                    param: "use_integers_for_enums",
108                    value: "true",
109                } => ret_val.use_integers_for_enums = true,
110                Param::Parameter {
111                    param: "no_include",
112                }
113                | Param::Value {
114                    param: "no_include",
115                    value: "true",
116                } => ret_val.no_include = true,
117                Param::Value {
118                    param: "no_include",
119                    value: "false",
120                } => (),
121                Param::KeyValue {
122                    param: "extern_path",
123                    key: prefix,
124                    value: module,
125                } => ret_val.extern_path.push((prefix.to_string(), module)),
126                _ => return Err(InvalidParameter::from(param)),
127            }
128        }
129
130        Ok(ret_val)
131    }
132}