diff --git a/proxmox-api-macro/src/api/enums.rs b/proxmox-api-macro/src/api/enums.rs index 1643fb2e..24bd3b9e 100644 --- a/proxmox-api-macro/src/api/enums.rs +++ b/proxmox-api-macro/src/api/enums.rs @@ -1,16 +1,32 @@ use std::convert::TryInto; -use std::mem; use failure::Error; use proc_macro2::{Ident, Span, TokenStream}; -use quote::{quote, quote_spanned}; +use quote::quote_spanned; +use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::Token; use super::Schema; use crate::util::{JSONObject, JSONValue, SimpleIdent}; +/// `parse_macro_input!` expects a TokenStream_1 +struct AttrArgs { + paren_token: syn::token::Paren, + args: Punctuated, +} + +impl Parse for AttrArgs { + fn parse(input: ParseStream) -> syn::Result { + let content; + Ok(Self { + paren_token: syn::parenthesized!(content in input), + args: Punctuated::parse_terminated(&content)?, + }) + } +} + /// Enums, provided they're simple enums, simply get an enum string schema attached to them. pub fn handle_enum( mut attribs: JSONObject, @@ -45,30 +61,24 @@ pub fn handle_enum( let mut renamed = false; for attrib in &mut variant.attrs { - if !attrib.path.is_ident("api") { + if !attrib.path.is_ident("serde") { continue; } - attrib.path = syn::parse2(quote! { serde })?; - - let mut obj: JSONObject = - syn::parse2(mem::replace(&mut attrib.tokens, TokenStream::new()))?; - match obj.remove("rename") { - Some(JSONValue::Expr(syn::Expr::Lit(lit))) => { - if let syn::Lit::Str(lit) = lit.lit { - attrib.tokens.extend(quote! { rename = #lit }); - variants.push(lit); - renamed = true; - } else { - bail!(attrib => "'rename' must be a literal string"); + let args: AttrArgs = syn::parse2(attrib.tokens.clone())?; + for arg in args.args { + match arg { + syn::NestedMeta::Meta(syn::Meta::NameValue(var)) => { + if var.path.is_ident("rename") { + match var.lit { + syn::Lit::Str(lit) => variants.push(lit), + _ => bail!(var.lit => "'rename' value must be a string literal"), + } + renamed = true; + } } + _ => (), // ignore } - Some(_) => bail!(attrib => "'rename' must be a literal string"), - None => (), - } - - if !obj.is_empty() { - bail!(attrib => "unknown fields in attribute"); } } diff --git a/proxmox-api-macro/tests/types.rs b/proxmox-api-macro/tests/types.rs index 96da6fdf..c1dde62b 100644 --- a/proxmox-api-macro/tests/types.rs +++ b/proxmox-api-macro/tests/types.rs @@ -5,7 +5,7 @@ use proxmox::api::schema; use proxmox_api_macro::api; use failure::Error; -//use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use serde_json::Value; #[api( @@ -24,7 +24,9 @@ impl OkString { } #[api(description: "A selection of either A, B or C")] +#[derive(Deserialize)] pub enum Selection { + #[serde(rename = "a")] A, B, C,