mirror of
https://git.proxmox.com/git/proxmox
synced 2025-06-14 22:12:48 +00:00
api: support #[default] attribute
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
0719e1db1c
commit
38a60d3acb
@ -25,6 +25,8 @@ pub fn handle_enum(
|
|||||||
error!(fmt.span(), "illegal key 'format', will be autogenerated");
|
error!(fmt.span(), "illegal key 'format', will be autogenerated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let has_default_attrib = attribs.get("default").map(|def| def.span());
|
||||||
|
|
||||||
let schema = {
|
let schema = {
|
||||||
let mut schema: Schema = attribs.try_into()?;
|
let mut schema: Schema = attribs.try_into()?;
|
||||||
|
|
||||||
@ -39,6 +41,8 @@ pub fn handle_enum(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let container_attrs = serde::ContainerAttrib::try_from(&enum_ty.attrs[..])?;
|
let container_attrs = serde::ContainerAttrib::try_from(&enum_ty.attrs[..])?;
|
||||||
|
let derives_default = util::derives_trait(&enum_ty.attrs, "Default");
|
||||||
|
let mut default_value = None;
|
||||||
|
|
||||||
let mut variants = TokenStream::new();
|
let mut variants = TokenStream::new();
|
||||||
for variant in &mut enum_ty.variants {
|
for variant in &mut enum_ty.variants {
|
||||||
@ -64,6 +68,21 @@ pub fn handle_enum(
|
|||||||
syn::LitStr::new(&name.to_string(), name.span())
|
syn::LitStr::new(&name.to_string(), name.span())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if derives_default {
|
||||||
|
if let Some(attr) = variant.attrs.iter().find(|a| a.path.is_ident("default")) {
|
||||||
|
if let Some(default_value) = &default_value {
|
||||||
|
error!(attr => "multiple default values defined");
|
||||||
|
error!(default_value => "default previously defined here");
|
||||||
|
} else {
|
||||||
|
default_value = Some(variant_string.clone());
|
||||||
|
if let Some(span) = has_default_attrib {
|
||||||
|
error!(attr => "#[default] attribute in use with 'default' #[api] key");
|
||||||
|
error!(span, "'default' also defined here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
variants.extend(quote_spanned! { variant.ident.span() =>
|
variants.extend(quote_spanned! { variant.ident.span() =>
|
||||||
::proxmox_schema::EnumEntry {
|
::proxmox_schema::EnumEntry {
|
||||||
value: #variant_string,
|
value: #variant_string,
|
||||||
@ -74,6 +93,11 @@ pub fn handle_enum(
|
|||||||
|
|
||||||
let name = &enum_ty.ident;
|
let name = &enum_ty.ident;
|
||||||
|
|
||||||
|
let default_value = match default_value {
|
||||||
|
Some(value) => quote_spanned!(value.span() => .default(#value)),
|
||||||
|
None => TokenStream::new(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(quote_spanned! { name.span() =>
|
Ok(quote_spanned! { name.span() =>
|
||||||
#enum_ty
|
#enum_ty
|
||||||
|
|
||||||
@ -81,6 +105,7 @@ pub fn handle_enum(
|
|||||||
const API_SCHEMA: ::proxmox_schema::Schema =
|
const API_SCHEMA: ::proxmox_schema::Schema =
|
||||||
#schema
|
#schema
|
||||||
.format(&::proxmox_schema::ApiStringFormat::Enum(&[#variants]))
|
.format(&::proxmox_schema::ApiStringFormat::Enum(&[#variants]))
|
||||||
|
#default_value
|
||||||
.schema();
|
.schema();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ fn derive_updater(
|
|||||||
let original_name = &original_struct.ident;
|
let original_name = &original_struct.ident;
|
||||||
stru.ident = Ident::new(&format!("{}Updater", stru.ident), stru.ident.span());
|
stru.ident = Ident::new(&format!("{}Updater", stru.ident), stru.ident.span());
|
||||||
|
|
||||||
if !util::derived_items(&original_struct.attrs).any(|p| p.is_ident("Default")) {
|
if !util::derives_trait(&original_struct.attrs, "Default") {
|
||||||
stru.attrs.push(util::make_derive_attribute(
|
stru.attrs.push(util::make_derive_attribute(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
quote::quote! { Default },
|
quote::quote! { Default },
|
||||||
|
@ -699,6 +699,11 @@ pub fn derived_items(attributes: &[syn::Attribute]) -> DerivedItems {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper to check if a certain trait is being derived.
|
||||||
|
pub fn derives_trait(attributes: &[syn::Attribute], ident: &str) -> bool {
|
||||||
|
derived_items(&attributes).any(|p| p.is_ident(ident))
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterator over the types found in `#[derive(...)]` attributes.
|
/// Iterator over the types found in `#[derive(...)]` attributes.
|
||||||
pub struct DerivedItems<'a> {
|
pub struct DerivedItems<'a> {
|
||||||
current: Option<<Punctuated<syn::NestedMeta, Token![,]> as IntoIterator>::IntoIter>,
|
current: Option<<Punctuated<syn::NestedMeta, Token![,]> as IntoIterator>::IntoIter>,
|
||||||
|
@ -103,7 +103,7 @@ fn renamed_struct() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[api]
|
#[api]
|
||||||
#[derive(Deserialize)]
|
#[derive(Default, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
/// A selection of either 'onekind', 'another-kind' or 'selection-number-three'.
|
/// A selection of either 'onekind', 'another-kind' or 'selection-number-three'.
|
||||||
pub enum Selection {
|
pub enum Selection {
|
||||||
@ -111,6 +111,7 @@ pub enum Selection {
|
|||||||
#[serde(rename = "onekind")]
|
#[serde(rename = "onekind")]
|
||||||
OneKind,
|
OneKind,
|
||||||
/// Some other kind.
|
/// Some other kind.
|
||||||
|
#[default]
|
||||||
AnotherKind,
|
AnotherKind,
|
||||||
/// And yet another.
|
/// And yet another.
|
||||||
SelectionNumberThree,
|
SelectionNumberThree,
|
||||||
@ -126,6 +127,7 @@ fn selection_test() {
|
|||||||
EnumEntry::new("another-kind", "Some other kind."),
|
EnumEntry::new("another-kind", "Some other kind."),
|
||||||
EnumEntry::new("selection-number-three", "And yet another."),
|
EnumEntry::new("selection-number-three", "And yet another."),
|
||||||
]))
|
]))
|
||||||
|
.default("another-kind")
|
||||||
.schema();
|
.schema();
|
||||||
|
|
||||||
assert_eq!(TEST_SCHEMA, Selection::API_SCHEMA);
|
assert_eq!(TEST_SCHEMA, Selection::API_SCHEMA);
|
||||||
|
Loading…
Reference in New Issue
Block a user