From 176e208caff3337fb0e4cfda94238807897035e7 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Mon, 23 Mar 2020 09:06:43 +0100 Subject: [PATCH] api-macro: add consts for defaults Not sure how we want to actually handle default values yet. For now we need to figure out what "feels best". This adds default values as publicly available consts so they can be accessed from anywhere as `API_METHOD__PARAM_DEFAULT_`. This is quite a handful to type, but I'm not sure how to make this better. Within the function body we also have the `api_get_default!(param_name)` macro which is more convenient, but not available outside the `#[api]` tagged function. Signed-off-by: Wolfgang Bumiller --- proxmox-api-macro/src/api/method.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/proxmox-api-macro/src/api/method.rs b/proxmox-api-macro/src/api/method.rs index f7089941..08a2b29f 100644 --- a/proxmox-api-macro/src/api/method.rs +++ b/proxmox-api-macro/src/api/method.rs @@ -49,12 +49,15 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result Result, func: &mut syn::ItemFn, wrapper_ts: &mut TokenStream, + default_consts: &mut TokenStream, ) -> Result { let sig = &func.sig; let is_async = sig.asyncness.is_some(); @@ -271,6 +277,7 @@ fn handle_function_signature( param_list, func, wrapper_ts, + default_consts, is_async, ) } @@ -327,6 +334,7 @@ fn create_wrapper_function( param_list: Vec<(FieldName, ParameterType)>, func: &syn::ItemFn, wrapper_ts: &mut TokenStream, + default_consts: &mut TokenStream, is_async: bool, ) -> Result { let api_func_name = Ident::new( @@ -337,6 +345,8 @@ fn create_wrapper_function( let mut body = TokenStream::new(); let mut args = TokenStream::new(); + let func_uc = func.sig.ident.to_string().to_uppercase(); + for (name, param) in param_list { let span = name.span(); match param { @@ -356,6 +366,7 @@ fn create_wrapper_function( .map(::serde_json::from_value) .transpose()? }); + let default_value = schema.find_schema_property("default"); if !optional { // Non-optional types need to be extracted out of the option though (unless // they have a default): @@ -371,7 +382,7 @@ fn create_wrapper_function( }); } else if util::is_option_type(ty).is_none() { // Optional parameter without an Option type requires a default: - if let Some(def) = schema.find_schema_property("default") { + if let Some(def) = &default_value { body.extend(quote_spanned! { span => .unwrap_or_else(|| #def) }); @@ -381,6 +392,19 @@ fn create_wrapper_function( } body.extend(quote_spanned! { span => ; }); args.extend(quote_spanned! { span => #arg_name, }); + + if let Some(def) = &default_value { + let name_uc = name.as_ident().to_string().to_uppercase(); + let name = Ident::new( + &format!("API_METHOD_{}_PARAM_DEFAULT_{}", func_uc, name_uc), + span, + ); + // strip possible Option<> from this type: + let ty = util::is_option_type(ty).unwrap_or(ty); + default_consts.extend(quote_spanned! { span => + pub const #name: #ty = #def; + }); + } } } }