actix_prost_build/
method.rs1use crate::{config::HttpRule, Request, Response};
2use proc_macro2::{Ident, TokenStream};
3
4pub struct Method {
5 name: Ident,
6 config: HttpRule,
8 trait_name: Ident,
9 request: Request,
10 response: Response,
11}
12
13impl Method {
14 pub fn new(
15 method: prost_build::Method,
16 request_message: syn::ItemStruct,
17 response_message: syn::ItemStruct,
18 config: HttpRule,
19 trait_name: Ident,
20 ) -> Method {
21 let method_name = quote::format_ident!("{}", method.proto_name);
22 let request = Request::new(request_message, method_name, &config);
24 let response = Response::new(response_message, config.response_body.clone());
25 Method {
26 name: quote::format_ident!("{}", method.name),
27 config,
29 trait_name,
30 request,
31 response,
32 }
33 }
34
35 pub fn method_name(&self) -> Ident {
36 quote::format_ident!("call_{}", self.name)
37 }
38
39 pub fn generate_config(&self) -> TokenStream {
40 let path = self.config.pattern.path();
41 let method_type = quote::format_ident!("{}", self.config.pattern.method());
42 let name = self.method_name();
43 quote::quote!(
44 config.route(#path, ::actix_web::web::#method_type().to(#name));
45 )
46 }
47
48 pub fn generate_route(&self) -> TokenStream {
49 let method_name = self.method_name();
50 let name = &self.name;
51 let trait_name = &self.trait_name;
52 let request_init = self.request.generate_new_request();
53 let extractors = self.request.generate_extractors();
54 let (payload, payload_convert) = if self.request.has_sub(self.request.body()) {
55 (
56 Some(quote::quote!(payload: ::actix_web::web::Payload,)),
57 Some(quote::quote!(let mut payload = payload.into_inner();)),
58 )
59 } else {
60 (None, None)
61 };
62 let response_convert = self.response.generate_convert();
63 quote::quote!(
64 async fn #method_name(
65 service: ::actix_web::web::Data<dyn #trait_name + Sync + Send + 'static>,
66 http_request: ::actix_web::HttpRequest,
67 #payload
68 ) -> Result<impl Responder, ::actix_prost::Error> {
69 #payload_convert
70 #extractors
71 let request = #request_init;
72 let request = ::actix_prost::new_request(request, &http_request);
73 let response = service
74 .#name(request)
75 .await?;
76 let headers = response.metadata().clone().into_headers();
77 let response = response.into_inner();
78 #response_convert
79 let mut json_response = ::actix_web::web::Json(response).customize();
80 for (key, value) in headers.iter() {
81 json_response = json_response.insert_header((key.as_str(), value.as_bytes()));
82 }
83 Ok(json_response)
84 }
85 )
86 }
87
88 pub fn request(&self) -> &Request {
89 &self.request
90 }
91}