]> git.proxmox.com Git - proxmox.git/commitdiff
Updater: take serde renames into account
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 24 Feb 2021 08:21:52 +0000 (09:21 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 24 Feb 2021 08:21:52 +0000 (09:21 +0100)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
proxmox-api-macro/src/updater.rs
proxmox-api-macro/tests/updater.rs

index 1ef82adc994665a37b9a6a1919f75bcff456f4db..2d037bd6250555e859864b04fffe27dae5b4ad05 100644 (file)
@@ -1,7 +1,10 @@
+use std::convert::TryFrom;
+
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote, quote_spanned};
 use syn::spanned::Spanned;
 
+use crate::serde;
 use crate::util;
 
 pub(crate) fn updatable(item: TokenStream) -> Result<TokenStream, syn::Error> {
@@ -90,6 +93,7 @@ fn derive_named_struct_updatable(
 ) -> Result<TokenStream, syn::Error> {
     no_generics(generics);
 
+    let serde_container_attrs = serde::ContainerAttrib::try_from(&attrs[..])?;
     let args = UpdatableArgs::from_attributes(attrs);
     let updater = match args.updater {
         Some(updater) => updater,
@@ -101,32 +105,41 @@ fn derive_named_struct_updatable(
     let mut build = TokenStream::new();
 
     for field in fields.named {
+        let serde_attrs = serde::SerdeAttrib::try_from(&field.attrs[..])?;
         let attrs = UpdaterFieldArgs::from_attributes(field.attrs);
 
-        let field_name = field
+        let field_ident = field
             .ident
             .as_ref()
             .expect("unnamed field in named struct?");
 
-        let field_name_string = field_name.to_string();
+        let field_name_string = if let Some(renamed) = serde_attrs.rename {
+            renamed.into_str()
+        } else if let Some(rename_all) = serde_container_attrs.rename_all {
+            let name = rename_all.apply_to_field(&field_ident.to_string());
+            name
+        } else {
+            field_ident.to_string()
+        };
+
         let build_err = format!(
             "failed to build value for field '{}': {{}}",
             field_name_string
         );
         if util::is_option_type(&field.ty).is_some() {
             delete.extend(quote! {
-                #field_name_string => { self.#field_name = None; }
+                #field_name_string => { self.#field_ident = None; }
             });
             build.extend(quote! {
-                #field_name: ::proxmox::api::schema::Updatable::try_build_from(
-                    from.#field_name
+                #field_ident: ::proxmox::api::schema::Updatable::try_build_from(
+                    from.#field_ident
                 )
                 .map_err(|err| ::anyhow::format_err!(#build_err, err))?,
             });
         } else {
             build.extend(quote! {
-                #field_name: ::proxmox::api::schema::Updatable::try_build_from(
-                    from.#field_name
+                #field_ident: ::proxmox::api::schema::Updatable::try_build_from(
+                    from.#field_ident
                 )
                 .map_err(|err| ::anyhow::format_err!(#build_err, err))?,
             });
@@ -135,18 +148,18 @@ fn derive_named_struct_updatable(
         if attrs.fixed {
             let error = format!(
                 "field '{}' must not be set when updating existing data",
-                field_name
+                field_ident
             );
             apply.extend(quote! {
-                if from.#field_name.is_some() {
+                if from.#field_ident.is_some() {
                     ::anyhow::bail!(#error);
                 }
             });
         } else {
             apply.extend(quote! {
                 ::proxmox::api::schema::Updatable::update_from(
-                    &mut self.#field_name,
-                    from.#field_name,
+                    &mut self.#field_ident,
+                    from.#field_ident,
                     delete,
                 )?;
             });
index b52c87a0dd04d3bde3e75f871e6094e0e515e55b..4af50dbbf0e747e3c2003de396b6f61f340f2479 100644 (file)
@@ -9,9 +9,10 @@ use proxmox::api::schema::{Updatable, Updater};
 /// An example of a simple struct type.
 #[cfg_attr(not(feature = "noserde"), derive(Deserialize, Serialize))]
 #[derive(Debug, PartialEq, Updater)]
+#[serde(rename_all = "kebab-case")]
 pub struct Simple {
     /// A test string.
-    one: String,
+    one_field: String,
 
     /// An optional auto-derived value for testing:
     #[serde(skip_serializing_if = "Option::is_empty")]
@@ -191,7 +192,7 @@ mod test_creatable {
                 "id": "Id1",
                 "name": "The Name",
                 "extra": "Extra Info",
-                "one": "Part of Simple",
+                "one-field": "Part of Simple",
                 "info2": "More Info 2",
             }),
             &API_METHOD_CREATE_THING,
@@ -209,7 +210,7 @@ mod test_creatable {
                 complex: Complex {
                     extra: "Extra Info".to_string(),
                     simple: Simple {
-                        one: "Part of Simple".to_string(),
+                        one_field: "Part of Simple".to_string(),
                         opt: None,
                     },
                 },
@@ -245,7 +246,7 @@ mod test_creatable {
                 complex: Complex {
                     extra: "Extra Info".to_string(),
                     simple: Simple {
-                        one: "Part of Simple".to_string(),
+                        one_field: "Part of Simple".to_string(),
                         opt: None,
                     },
                 },
@@ -270,7 +271,7 @@ mod test_creatable {
                 complex: Complex {
                     extra: "Partial flatten update".to_string(),
                     simple: Simple {
-                        one: "Part of Simple".to_string(),
+                        one_field: "Part of Simple".to_string(),
                         opt: None,
                     },
                 },
@@ -295,7 +296,7 @@ mod test_creatable {
                 complex: Complex {
                     extra: "Partial flatten update".to_string(),
                     simple: Simple {
-                        one: "Part of Simple".to_string(),
+                        one_field: "Part of Simple".to_string(),
                         opt: Some("Deeply nested optional update.".to_string()),
                     },
                 },
@@ -320,7 +321,7 @@ mod test_creatable {
                 complex: Complex {
                     extra: "Partial flatten update".to_string(),
                     simple: Simple {
-                        one: "Part of Simple".to_string(),
+                        one_field: "Part of Simple".to_string(),
                         opt: None,
                     },
                 },