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