1pub mod builder;
2pub mod codegen;
3pub mod generator;
4
5pub use builder::ProstBuilder;
6
7use proc_macro2::TokenStream;
8use prost_build::{Method as PMethod, Service as PService};
9use quote::ToTokens;
10
11use crate::utils::{Method, Service};
12
13impl Service for PService {
14 type Comment = String;
15 type Method = PMethod;
16
17 fn name(&self) -> &str {
18 &self.name
19 }
20
21 fn package(&self) -> &str {
22 &self.package
23 }
24
25 fn identifier(&self) -> &str {
26 &self.proto_name
27 }
28
29 fn methods(&self) -> &[Self::Method] {
30 &self.methods
31 }
32
33 fn comment(&self) -> &[Self::Comment] {
34 &self.comments.leading[..]
35 }
36}
37
38const NON_PATH_TYPE_ALLOWLIST: &[&str] = &["()"];
39
40impl Method for PMethod {
41 type Comment = String;
42
43 fn name(&self) -> &str {
44 &self.name
45 }
46
47 fn identifier(&self) -> &str {
48 &self.proto_name
49 }
50
51 fn client_streaming(&self) -> bool {
52 self.client_streaming
53 }
54
55 fn server_streaming(&self) -> bool {
56 self.server_streaming
57 }
58
59 fn comment(&self) -> &[Self::Comment] {
60 &self.comments.leading[..]
61 }
62
63 fn request_response_name(
64 &self,
65 proto_path: &str,
66 compile_well_known_types: bool,
67 ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
68 let request = convert_type(
69 compile_well_known_types,
70 proto_path,
71 &self.input_proto_type,
72 &self.input_type,
73 );
74 let response = convert_type(
75 compile_well_known_types,
76 proto_path,
77 &self.output_proto_type,
78 &self.output_type,
79 );
80 (request, response)
81 }
82}
83
84fn convert_type(
85 compile_well_known_types: bool,
86 proto_path: &str,
87 proto_type: &str,
88 rust_type: &str,
89) -> TokenStream {
90 if (is_google_type(proto_type) && !compile_well_known_types)
91 || rust_type.starts_with("::")
92 || NON_PATH_TYPE_ALLOWLIST.iter().any(|ty| *ty == rust_type)
93 {
94 rust_type.parse::<TokenStream>().unwrap()
95 } else if rust_type.starts_with("crate::") {
96 syn::parse_str::<syn::Path>(rust_type)
97 .unwrap()
98 .to_token_stream()
99 } else {
100 syn::parse_str::<syn::Path>(&format!("{}::{}", proto_path, rust_type))
101 .unwrap()
102 .to_token_stream()
103 }
104}
105
106fn is_google_type(ty: &str) -> bool {
107 ty.starts_with(".google.protobuf")
108}