mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-13 16:08:00 +00:00
Updater: take serde renames into account
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
d3636d45d9
commit
857b8ab2b9
@ -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,
|
||||
)?;
|
||||
});
|
||||
|
@ -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,
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user