From c8c5fdc2d0998c3f691b04876d000b7470dd9d2c Mon Sep 17 00:00:00 2001 From: Alexander Polakov Date: Thu, 27 Jul 2023 20:11:46 +0400 Subject: [PATCH] feat: flatten request --- proc-macros/src/render_server.rs | 12 ++++++++++-- proc-macros/src/rpc_macro.rs | 12 +++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/proc-macros/src/render_server.rs b/proc-macros/src/render_server.rs index 9f9e0facba..989da82cde 100644 --- a/proc-macros/src/render_server.rs +++ b/proc-macros/src/render_server.rs @@ -127,7 +127,7 @@ impl RpcDescription { // provided `Params` object. // `params_seq` is the comma-delimited sequence of parameters we're passing to the rust function // called.. - let (parsing, params_seq) = self.render_params_decoding(&method.params, None); + let (parsing, params_seq) = self.render_params_decoding(&method.params, None, method.flatten); let into_response = self.jrps_server_item(quote! { IntoResponse }); @@ -170,7 +170,7 @@ impl RpcDescription { // provided `Params` object. // `params_seq` is the comma-delimited sequence of parameters. let pending = proc_macro2::Ident::new("subscription_sink", rust_method_name.span()); - let (parsing, params_seq) = self.render_params_decoding(&sub.params, Some(pending)); + let (parsing, params_seq) = self.render_params_decoding(&sub.params, Some(pending), false); let into_sub_response = self.jrps_server_item(quote! { IntoSubscriptionCloseResponse }); check_name(&rpc_sub_name, rust_method_name.span()); @@ -279,6 +279,7 @@ impl RpcDescription { &self, params: &[(syn::PatIdent, syn::Type)], sub: Option, + flatten: bool, ) -> (TokenStream2, TokenStream2) { if params.is_empty() { return (TokenStream2::default(), TokenStream2::default()); @@ -380,8 +381,15 @@ impl RpcDescription { tokens: TokenStream2::from_str(&format!("({})", alias_vals.as_str())).unwrap(), }; + let serde_flatten = if flatten { + quote! { #[serde(flatten)] } + } else { + quote! {} + }; + quote! { #serde_alias + #serde_flatten #name: #ty, } }); diff --git a/proc-macros/src/rpc_macro.rs b/proc-macros/src/rpc_macro.rs index 738f2d802e..0a26c3192b 100644 --- a/proc-macros/src/rpc_macro.rs +++ b/proc-macros/src/rpc_macro.rs @@ -48,17 +48,19 @@ pub struct RpcMethod { pub returns: Option, pub signature: syn::TraitItemMethod, pub aliases: Vec, + pub flatten: bool, } impl RpcMethod { pub fn from_item(attr: Attribute, mut method: syn::TraitItemMethod) -> syn::Result { - let [aliases, blocking, name, param_kind] = - AttributeMeta::parse(attr)?.retain(["aliases", "blocking", "name", "param_kind"])?; + let [aliases, blocking, name, param_kind, flatten] = + AttributeMeta::parse(attr)?.retain(["aliases", "blocking", "name", "param_kind", "flatten"])?; let aliases = parse_aliases(aliases)?; let blocking = optional(blocking, Argument::flag)?.is_some(); let name = name?.string()?; let param_kind = parse_param_kind(param_kind)?; + let flatten = optional(flatten, Argument::flag)?.is_some(); let sig = method.sig.clone(); let docs = extract_doc_comments(&method.attrs); @@ -67,6 +69,10 @@ impl RpcMethod { None => quote!(), }; + if flatten && !matches!(param_kind, ParamKind::Map) { + return Err(syn::Error::new(sig.span(), "Flatten request must have param_kind=map")); + } + if blocking && sig.asyncness.is_some() { return Err(syn::Error::new(sig.span(), "Blocking method must be synchronous")); } @@ -98,7 +104,7 @@ impl RpcMethod { // We've analyzed attributes and don't need them anymore. method.attrs.clear(); - Ok(Self { aliases, blocking, name, params, param_kind, returns, signature: method, docs, deprecated }) + Ok(Self { aliases, blocking, name, params, param_kind, returns, signature: method, docs, deprecated, flatten }) } }