kanamaru_build/prost/
generator.rs

1use proc_macro2::TokenStream;
2use prost_build::ServiceGenerator as SVCGen;
3use quote::ToTokens;
4
5use super::{codegen::CodegenResponderBuilder, ProstBuilder};
6
7pub struct ServiceGenerator {
8    builder: ProstBuilder,
9    responder: TokenStream,
10}
11
12impl ServiceGenerator {
13    pub fn new(builder: ProstBuilder) -> Self {
14        Self {
15            builder,
16            responder: TokenStream::new(),
17        }
18    }
19}
20
21impl SVCGen for ServiceGenerator {
22    fn generate(&mut self, service: prost_build::Service, _buf: &mut String) {
23        let responder = CodegenResponderBuilder {
24            service: &service,
25            emit_package: self.builder.emit_package,
26            proto_path: &self.builder.proto_path,
27            compile_well_known_types: self.builder.compile_well_known_types,
28            use_arc_self: self.builder.use_arc_self,
29            generate_default_stubs: self.builder.generate_default_stubs,
30            attributes: &self.builder.responder_attributes,
31            disabled_comments: &self.builder.disable_comments,
32        };
33
34        self.responder.extend(responder.into_token_stream());
35    }
36    fn finalize(&mut self, buf: &mut String) {
37        if !self.responder.is_empty() {
38            let responder = &self.responder;
39
40            let responder_service = quote::quote! {
41                #responder
42            };
43
44            let ast: syn::File = syn::parse2(responder_service).expect("not a valid tokenstream");
45            let code = prettyplease::unparse(&ast);
46            buf.push_str(&code);
47
48            self.responder = TokenStream::default();
49        }
50    }
51}