From: Wolfgang Bumiller <w.bumiller@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox 13/18] api-macro: factor parameter extraction into a function
Date: Fri, 18 Dec 2020 12:26:01 +0100 [thread overview]
Message-ID: <20201218112608.6845-14-w.bumiller@proxmox.com> (raw)
In-Reply-To: <20201218112608.6845-1-w.bumiller@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
proxmox-api-macro/src/api/method.rs | 142 +++++++++++++++++-----------
1 file changed, 85 insertions(+), 57 deletions(-)
diff --git a/proxmox-api-macro/src/api/method.rs b/proxmox-api-macro/src/api/method.rs
index 3d6e9ed..ff5d3e0 100644
--- a/proxmox-api-macro/src/api/method.rs
+++ b/proxmox-api-macro/src/api/method.rs
@@ -458,63 +458,15 @@ fn create_wrapper_function(
ParameterType::ApiMethod => args.extend(quote_spanned! { span => api_method_param, }),
ParameterType::RpcEnv => args.extend(quote_spanned! { span => rpc_env_param, }),
ParameterType::Normal(param) => {
- let name_str = syn::LitStr::new(name.as_str(), span);
- let arg_name =
- Ident::new(&format!("input_arg_{}", name.as_ident().to_string()), span);
-
- // Optional parameters are expected to be Option<> types in the real function
- // signature, so we can just keep the returned Option from `input_map.remove()`.
- body.extend(quote_spanned! { span =>
- let #arg_name = input_map
- .remove(#name_str)
- .map(::serde_json::from_value)
- .transpose()?
- });
- let default_value = param.entry.schema.find_schema_property("default");
- if !param.entry.optional {
- // Non-optional types need to be extracted out of the option though (unless
- // they have a default):
- //
- // Whether the parameter is optional should have been verified by the schema
- // verifier already, so here we just use anyhow::bail! instead of building a
- // proper http error!
- body.extend(quote_spanned! { span =>
- .ok_or_else(|| ::anyhow::format_err!(
- "missing non-optional parameter: {}",
- #name_str,
- ))?
- });
- }
- let no_option_type = util::is_option_type(param.ty).is_none();
-
- 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(param.ty).unwrap_or(param.ty);
- default_consts.extend(quote_spanned! { span =>
- pub const #name: #ty = #def;
- });
- if param.entry.optional && no_option_type {
- // Optional parameter without an Option<T> type requires a default:
- body.extend(quote_spanned! { span =>
- .unwrap_or(#name)
- });
- }
- } else if param.entry.optional && no_option_type {
- // FIXME: we should not be able to reach this without having produced another
- // error above already anyway?
- error!(param.ty => "Optional parameter without Option<T> requires a default");
- // we produced an error so just write something that will compile
- body.extend(quote_spanned! { span =>
- .unwrap_or_else(|| unreachable!())
- });
- }
- body.extend(quote_spanned! { span => ; });
- args.extend(quote_spanned! { span => #arg_name, });
+ extract_normal_parameter(
+ param,
+ &mut body,
+ &mut args,
+ &func_uc,
+ name,
+ span,
+ default_consts,
+ )?;
}
}
}
@@ -573,6 +525,82 @@ fn create_wrapper_function(
Ok(api_func_name)
}
+fn extract_normal_parameter(
+ param: NormalParameter,
+ body: &mut TokenStream,
+ args: &mut TokenStream,
+ func_uc: &str,
+ name: FieldName,
+ name_span: Span,
+ default_consts: &mut TokenStream,
+) -> Result<(), Error> {
+ let span = name_span; // renamed during refactorization
+ let name_str = syn::LitStr::new(name.as_str(), span);
+ let arg_name = Ident::new(&format!("input_arg_{}", name.as_ident().to_string()), span);
+
+ // Optional parameters are expected to be Option<> types in the real function
+ // signature, so we can just keep the returned Option from `input_map.remove()`.
+ body.extend(quote_spanned! { span =>
+ let #arg_name = input_map
+ .remove(#name_str)
+ .map(::serde_json::from_value)
+ .transpose()?
+ });
+
+ let default_value = param.entry.schema.find_schema_property("default");
+ if !param.entry.optional {
+ // Non-optional types need to be extracted out of the option though (unless
+ // they have a default):
+ //
+ // Whether the parameter is optional should have been verified by the schema
+ // verifier already, so here we just use anyhow::bail! instead of building a
+ // proper http error!
+ body.extend(quote_spanned! { span =>
+ .ok_or_else(|| ::anyhow::format_err!(
+ "missing non-optional parameter: {}",
+ #name_str,
+ ))?
+ });
+ }
+
+ let no_option_type = util::is_option_type(param.ty).is_none();
+
+ 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(param.ty).unwrap_or(param.ty);
+ default_consts.extend(quote_spanned! { span =>
+ pub const #name: #ty = #def;
+ });
+
+ if param.entry.optional && no_option_type {
+ // Optional parameter without an Option<T> type requires a default:
+ body.extend(quote_spanned! { span =>
+ .unwrap_or(#name)
+ });
+ }
+ } else if param.entry.optional && no_option_type {
+ // FIXME: we should not be able to reach this without having produced another
+ // error above already anyway?
+ error!(param.ty => "Optional parameter without Option<T> requires a default");
+
+ // we produced an error so just write something that will compile
+ body.extend(quote_spanned! { span =>
+ .unwrap_or_else(|| unreachable!())
+ });
+ }
+
+ body.extend(quote_spanned! { span => ; });
+ args.extend(quote_spanned! { span => #arg_name, });
+
+ Ok(())
+}
+
struct DefaultParameters<'a>(&'a Schema);
impl<'a> VisitMut for DefaultParameters<'a> {
--
2.20.1
next prev parent reply other threads:[~2020-12-18 11:37 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-18 11:25 [pbs-devel] [PATCH proxmox 00/18] Optional Return Types and AllOf schema Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 01/18] formatting fixup Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 02/18] schema: support optional return values Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 03/18] api-macro: " Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 04/18] schema: support AllOf schemas Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 05/18] schema: allow AllOf schema as method parameter Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 06/18] api-macro: add 'flatten' to SerdeAttrib Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 07/18] api-macro: forbid flattened fields Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 08/18] api-macro: add more standard Maybe methods Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 09/18] api-macro: suport AllOf on structs Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 10/18] schema: ExtractValueDeserializer Wolfgang Bumiller
2020-12-18 11:25 ` [pbs-devel] [PATCH proxmox 11/18] api-macro: object schema entry tuple -> struct Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH proxmox 12/18] api-macro: more tuple refactoring Wolfgang Bumiller
2020-12-18 11:26 ` Wolfgang Bumiller [this message]
2020-12-18 11:26 ` [pbs-devel] [PATCH proxmox 14/18] api-macro: support flattened parameters Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH proxmox 15/18] schema: ParameterSchema at 'api' level Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH proxmox 16/18] proxmox: temporary d/changelog update Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH proxmox 17/18] macro: " Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH proxmox 18/18] proxmox changelog update Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH backup 1/2] adaptions for proxmox 0.9 and proxmox-api-macro 0.3 Wolfgang Bumiller
2020-12-18 11:26 ` [pbs-devel] [PATCH backup 2/2] tests: verify-api: check AllOf schemas Wolfgang Bumiller
2020-12-22 6:45 ` [pbs-devel] [PATCH proxmox 00/18] Optional Return Types and AllOf schema Dietmar Maurer
2020-12-22 6:51 ` Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201218112608.6845-14-w.bumiller@proxmox.com \
--to=w.bumiller@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox