kanamaru_build/
prost.rs

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}