From 9351e89240200cf60d02c28c4fe13be8c1ffc3c5 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Mon, 1 Aug 2022 09:57:53 -0600 Subject: [PATCH] serde style defaults --- .../src/command/build.rs | 30 +++++++++++++++---- .../src/command/mod.rs | 2 +- .../src/command/parse.rs | 7 +++-- rpc-toolkit/tests/test.rs | 2 +- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/rpc-toolkit-macro-internals/src/command/build.rs b/rpc-toolkit-macro-internals/src/command/build.rs index 1d562fc..3f5c5ea 100644 --- a/rpc-toolkit-macro-internals/src/command/build.rs +++ b/rpc-toolkit-macro-internals/src/command/build.rs @@ -293,9 +293,9 @@ fn build_app(name: LitStr, opt: &mut Options, params: &mut [ParamType]) -> Token modifications.extend(quote_spanned! { ty_span => arg = arg.takes_value(true); }); - if let Some(default) = &arg.default { + if let Some(_) = &arg.default { modifications.extend(quote_spanned! { ty_span => - arg = arg.default_value(#default); + arg = arg.required(false); }); } else if p.path.segments.last().unwrap().ident == "Option" { arg.optional = true; @@ -485,10 +485,26 @@ fn rpc_handler( .unwrap_or_else(|| LitStr::new(&name.to_string(), name.span())); let field_name = Ident::new(&format!("arg_{}", name), name.span()); let ty = arg.ty.clone(); - param_def.push(quote! { + let def = quote! { #[serde(rename = #rename)] #field_name: #ty, - }) + }; + let def = match &arg.default { + Some(Some(default)) => { + quote! { + #[serde(default = #default)] + #def + } + } + Some(None) => { + quote! { + #[serde(default)] + #def + } + } + None => def, + }; + param_def.push(def); } ParamType::ParentData(ty) => parent_data_ty = quote! { #ty }, _ => (), @@ -780,6 +796,10 @@ fn cli_handler( .unwrap_or_else(|| LitStr::new(&name.to_string(), name.span())); let field_name = Ident::new(&format!("arg_{}", name), name.span()); let ty = arg.ty.clone(); + let mut ty = quote! { #ty }; + if arg.default.is_some() && !arg.optional { + ty = quote! { Option<#ty> }; + } arg_def.push(quote! { #[serde(rename = #rename)] #field_name: #ty, @@ -829,7 +849,7 @@ fn cli_handler( ::rpc_toolkit::command_helpers::prelude::default_arg_parser(arg_val, matches) } }; - if arg.optional { + if arg.optional || arg.default.is_some() { quote! { #field_name: if let Some(arg_val) = matches.value_of(#arg_name) { Some(#parse_val?) diff --git a/rpc-toolkit-macro-internals/src/command/mod.rs b/rpc-toolkit-macro-internals/src/command/mod.rs index fda2e64..3876d78 100644 --- a/rpc-toolkit-macro-internals/src/command/mod.rs +++ b/rpc-toolkit-macro-internals/src/command/mod.rs @@ -89,7 +89,7 @@ pub struct ArgOptions { short: Option, long: Option, parse: Option, - default: Option, + default: Option>, count: Option, multiple: Option, stdin: Option, diff --git a/rpc-toolkit-macro-internals/src/command/parse.rs b/rpc-toolkit-macro-internals/src/command/parse.rs index ee5ede8..d2bf990 100644 --- a/rpc-toolkit-macro-internals/src/command/parse.rs +++ b/rpc-toolkit-macro-internals/src/command/parse.rs @@ -785,7 +785,7 @@ pub fn parse_arg_attr(attr: Attribute, arg: PatType) -> Result { "duplicate argument `default`", )); } - opt.default = Some(default); + opt.default = Some(Some(default)); } else { return Err(Error::new(nv.lit.span(), "`default` must be a string")); } @@ -797,7 +797,10 @@ pub fn parse_arg_attr(attr: Attribute, arg: PatType) -> Result { )); } NestedMeta::Meta(Meta::Path(p)) if p.is_ident("default") => { - return Err(Error::new(p.span(), "`default` must be assigned to")); + if opt.default.is_some() { + return Err(Error::new(p.span(), "duplicate argument `default`")); + } + opt.default = Some(None); } _ => { return Err(Error::new(arg.span(), "unknown argument")); diff --git a/rpc-toolkit/tests/test.rs b/rpc-toolkit/tests/test.rs index a7df38d..9991c0b 100644 --- a/rpc-toolkit/tests/test.rs +++ b/rpc-toolkit/tests/test.rs @@ -53,7 +53,7 @@ async fn dothething< #[context] _ctx: AppState, #[arg(short = 'a')] arg1: Option, #[arg(short = 'b')] val: String, - #[arg(short = 'c', help = "I am the flag `c`!")] arg3: bool, + #[arg(short = 'c', help = "I am the flag `c`!", default)] arg3: bool, #[arg(stdin)] structured: U, ) -> Result<(Option, String, bool, U), RpcError> { Ok((arg1, val, arg3, structured))