-
Notifications
You must be signed in to change notification settings - Fork 265
Client call with named params #541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
4bf380d
c65efae
187078a
167612f
4cfa00b
f158a7f
b0fefbc
2e266c7
7baf3be
097276c
66488b2
95a945c
2d20978
510048f
a6850ae
d750f40
36bab4e
4721ce2
e7abc09
38bb7f0
0d4bb3c
82257ea
1933993
e7e0cd5
2c69f44
15a5b8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,37 +1,63 @@ | ||
| use proc_macro::TokenStream; | ||
| use std::str::FromStr; | ||
|
|
||
| use crate::params_style::ParamStyle; | ||
| use crate::rpc_attr::path_eq_str; | ||
|
|
||
| const CLIENT_META_WORD: &str = "client"; | ||
| const SERVER_META_WORD: &str = "server"; | ||
| const PARAMS_META_KEY: &str = "params"; | ||
|
|
||
| #[derive(Debug)] | ||
| pub struct DeriveOptions { | ||
| pub enable_client: bool, | ||
| pub enable_server: bool, | ||
| pub params_style: ParamStyle, | ||
| } | ||
|
|
||
| impl DeriveOptions { | ||
| pub fn new(enable_client: bool, enable_server: bool) -> Self { | ||
| pub fn new(enable_client: bool, enable_server: bool, params_style: ParamStyle) -> Self { | ||
| DeriveOptions { | ||
| enable_client, | ||
| enable_server, | ||
| params_style, | ||
| } | ||
| } | ||
|
|
||
| pub fn try_from(tokens: TokenStream) -> Result<Self, syn::Error> { | ||
| if tokens.is_empty() { | ||
| return Ok(Self::new(true, true)); | ||
| } | ||
| let ident: syn::Ident = syn::parse::<syn::Ident>(tokens)?; | ||
| let options = { | ||
| let ident = ident.to_string(); | ||
| if ident == "client" { | ||
| Some(Self::new(true, false)) | ||
| } else if ident == "server" { | ||
| Some(Self::new(false, true)) | ||
| } else { | ||
| None | ||
| pub fn try_from(args: syn::AttributeArgs) -> Result<Self, syn::Error> { | ||
| let mut options = DeriveOptions::new(false, false, ParamStyle::default()); | ||
| for arg in args { | ||
| if let syn::NestedMeta::Meta(meta) = arg { | ||
| match meta { | ||
| syn::Meta::Path(p) => { | ||
| match p.get_ident().unwrap().to_string().as_ref() { | ||
| CLIENT_META_WORD => options.enable_client = true, | ||
| SERVER_META_WORD => options.enable_server = true, | ||
| _ => {} | ||
| }; | ||
| } | ||
| syn::Meta::NameValue(nv) => { | ||
| if path_eq_str(&nv.path, PARAMS_META_KEY) { | ||
| if let syn::Lit::Str(ref lit) = nv.lit { | ||
| options.params_style = ParamStyle::from_str(&lit.value()) | ||
| .map_err(|e| syn::Error::new_spanned(nv.clone(), e))?; | ||
| } | ||
| } else { | ||
| return Err(syn::Error::new_spanned(nv, "Unexpected RPC attribute key")); | ||
| } | ||
| } | ||
| _ => return Err(syn::Error::new_spanned(meta, "Unexpected use of RPC attribute macro")), | ||
| } | ||
| } | ||
| }; | ||
| match options { | ||
| Some(options) => Ok(options), | ||
| None => Err(syn::Error::new(ident.span(), "Unknown attribute.")), | ||
| } | ||
| if !options.enable_client && !options.enable_server { | ||
| // if nothing provided default to both | ||
| options.enable_client = true; | ||
| options.enable_server = true; | ||
| } | ||
| if options.enable_server && options.params_style == ParamStyle::Named { | ||
| // This is not allowed at this time | ||
| panic!("Server code generation only supports `params = \"positional\"` at this time. This is the default setting.") | ||
|
willemolding marked this conversation as resolved.
Outdated
|
||
| } | ||
| Ok(options) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| use std::str::FromStr; | ||
|
|
||
| const POSITIONAL: &str = "positional"; | ||
| const NAMED: &str = "named"; | ||
| const RAW: &str = "raw"; | ||
|
|
||
| #[derive(Clone, Debug, PartialEq)] | ||
| pub enum ParamStyle { | ||
| Positional, | ||
| Named, | ||
| Raw, | ||
| } | ||
|
|
||
| impl Default for ParamStyle { | ||
| fn default() -> Self { | ||
| Self::Positional | ||
| } | ||
| } | ||
|
|
||
| impl FromStr for ParamStyle { | ||
| type Err = String; | ||
|
|
||
| fn from_str(s: &str) -> Result<Self, String> { | ||
| match s { | ||
| POSITIONAL => Ok(Self::Positional), | ||
| NAMED => Ok(Self::Named), | ||
| RAW => Ok(Self::Raw), | ||
| _ => Err(format!( | ||
| "Invalid value for params key. Must be one of [{}, {}, {}]", | ||
| POSITIONAL, NAMED, RAW | ||
| )), | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| use crate::params_style::ParamStyle; | ||
| use std::str::FromStr; | ||
| use syn::{ | ||
| visit::{self, Visit}, | ||
| Error, Result, | ||
|
|
@@ -9,7 +11,7 @@ pub struct RpcMethodAttribute { | |
| pub name: String, | ||
| pub aliases: Vec<String>, | ||
| pub kind: AttributeKind, | ||
| pub raw_params: bool, | ||
| pub params_style: Option<ParamStyle>, // None means do not override the top level default | ||
| } | ||
|
|
||
| #[derive(Clone, Debug)] | ||
|
|
@@ -37,10 +39,11 @@ const SUBSCRIPTION_NAME_KEY: &str = "subscription"; | |
| const ALIASES_KEY: &str = "alias"; | ||
| const PUB_SUB_ATTR_NAME: &str = "pubsub"; | ||
| const METADATA_META_WORD: &str = "meta"; | ||
| const RAW_PARAMS_META_WORD: &str = "raw_params"; | ||
| const RAW_PARAMS_META_WORD: &str = "raw_params"; // to be deprecated and replaced with `params = "raw"` | ||
| const SUBSCRIBE_META_WORD: &str = "subscribe"; | ||
| const UNSUBSCRIBE_META_WORD: &str = "unsubscribe"; | ||
| const RETURNS_META_WORD: &str = "returns"; | ||
| const PARAMS_STYLE_KEY: &str = "params"; | ||
|
|
||
| const MULTIPLE_RPC_ATTRIBUTES_ERR: &str = "Expected only a single rpc attribute per method"; | ||
| const INVALID_ATTR_PARAM_NAMES_ERR: &str = "Invalid attribute parameter(s):"; | ||
|
|
@@ -81,12 +84,18 @@ impl RpcMethodAttribute { | |
| let aliases = get_meta_list(&meta).map_or(Vec::new(), |ml| get_aliases(ml)); | ||
| let raw_params = | ||
| get_meta_list(meta).map_or(false, |ml| has_meta_word(RAW_PARAMS_META_WORD, ml)); | ||
| let params_style = match raw_params { | ||
| true => Ok(Some(ParamStyle::Raw)), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we print a deprecation warning here?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately I can't figure out a way to emit a warning without using the Not sure if we have any other ideas for this or if it is ok to just add a depreciation note to the docs but not the macro
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think in the past we simply used to
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we did use a simple |
||
| false => { | ||
| get_meta_list(meta).map_or(Ok(None), |ml| get_params_style(ml).map(|s| Some(s))) | ||
| } | ||
| }?; | ||
| Ok(RpcMethodAttribute { | ||
| attr: attr.clone(), | ||
| name, | ||
| aliases, | ||
| kind, | ||
| raw_params, | ||
| params_style, | ||
| }) | ||
| }) | ||
| }) | ||
|
|
@@ -179,7 +188,11 @@ fn validate_attribute_meta(meta: syn::Meta) -> Result<syn::Meta> { | |
| match ident.as_ref().map(String::as_str) { | ||
| Some(RPC_ATTR_NAME) => { | ||
| validate_idents(&meta, &visitor.meta_words, &[METADATA_META_WORD, RAW_PARAMS_META_WORD])?; | ||
| validate_idents(&meta, &visitor.name_value_names, &[RPC_NAME_KEY, RETURNS_META_WORD])?; | ||
| validate_idents( | ||
| &meta, | ||
| &visitor.name_value_names, | ||
| &[RPC_NAME_KEY, RETURNS_META_WORD, PARAMS_STYLE_KEY], | ||
| )?; | ||
| validate_idents(&meta, &visitor.meta_list_names, &[ALIASES_KEY]) | ||
| } | ||
| Some(PUB_SUB_ATTR_NAME) => { | ||
|
|
@@ -279,7 +292,13 @@ fn get_aliases(ml: &syn::MetaList) -> Vec<String> { | |
| }) | ||
| } | ||
|
|
||
| fn path_eq_str(path: &syn::Path, s: &str) -> bool { | ||
| fn get_params_style(ml: &syn::MetaList) -> Result<ParamStyle> { | ||
| get_name_value(PARAMS_STYLE_KEY, ml).map_or(Ok(ParamStyle::default()), |s| { | ||
| ParamStyle::from_str(&s).map_err(|e| Error::new_spanned(ml, e)) | ||
| }) | ||
| } | ||
|
|
||
| pub fn path_eq_str(path: &syn::Path, s: &str) -> bool { | ||
| path.get_ident().map_or(false, |i| i == s) | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.