]> git.proxmox.com Git - proxmox.git/commitdiff
api-macro: add VariantAttrib
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 6 Dec 2023 12:53:48 +0000 (13:53 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 6 Dec 2023 13:39:47 +0000 (14:39 +0100)
separated out of FieldAttrib without the `flatten` attribute, since we
don't support this on enum variants

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
proxmox-api-macro/src/api/enums.rs
proxmox-api-macro/src/serde.rs

index 16dbbe7b30290cd7540b784013cfb64e97ec7f6c..2ad7ac821afe0b75a1dd403340322fb2a19f2ebe 100644 (file)
@@ -57,7 +57,7 @@ pub fn handle_enum(
             comment = "<missing description>".to_string();
         }
 
-        let attrs = serde::FieldAttrib::try_from(&variant.attrs[..])?;
+        let attrs = serde::VariantAttrib::try_from(&variant.attrs[..])?;
         let variant_string = if let Some(renamed) = attrs.rename {
             renamed
         } else if let Some(rename_all) = container_attrs.rename_all {
index 4cb21ce795e1956718e8b7b6261ad633fcbdd733..d378405be589cd1a71a0d01ecf2246d4ecc42ee3 100644 (file)
@@ -166,7 +166,7 @@ impl TryFrom<&[syn::Attribute]> for ContainerAttrib {
     }
 }
 
-/// `serde` field/variant attributes we support
+/// `serde` field attributes we support
 #[derive(Default)]
 pub struct FieldAttrib {
     pub rename: Option<syn::LitStr>,
@@ -220,3 +220,54 @@ impl TryFrom<&[syn::Attribute]> for FieldAttrib {
         Ok(this)
     }
 }
+
+/// `serde` variant attributes we support
+#[derive(Default)]
+pub struct VariantAttrib {
+    pub rename: Option<syn::LitStr>,
+}
+
+impl VariantAttrib {
+    pub fn parse_attribute(&mut self, attrib: &syn::Attribute) -> Result<(), syn::Error> {
+        let list = match &attrib.meta {
+            syn::Meta::List(list) if list.path.is_ident("serde") => list,
+            _ => return Ok(()),
+        };
+
+        let args = list.parse_args_with(Punctuated::<syn::Meta, Token![,]>::parse_terminated)?;
+
+        for arg in args {
+            let path = arg.path();
+            if path.is_ident("rename") {
+                match &arg.require_name_value()?.value {
+                    syn::Expr::Lit(syn::ExprLit {
+                        lit: syn::Lit::Str(rename),
+                        ..
+                    }) => {
+                        if self.rename.is_some() && self.rename.as_ref() != Some(rename) {
+                            error!(&rename => "multiple conflicting 'rename' attributes");
+                        }
+                        self.rename = Some(rename.clone());
+                    }
+                    value => error!(value => "'rename' value must be a string literal"),
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl TryFrom<&[syn::Attribute]> for VariantAttrib {
+    type Error = syn::Error;
+
+    fn try_from(attributes: &[syn::Attribute]) -> Result<Self, syn::Error> {
+        let mut this: Self = Default::default();
+
+        for attrib in attributes {
+            this.parse_attribute(attrib)?;
+        }
+
+        Ok(this)
+    }
+}