Generate everything strum does myself (no duplicate prop names)

This commit is contained in:
Lennart
2025-01-18 20:00:26 +01:00
parent 39beee2f69
commit 8d1202234d
16 changed files with 69 additions and 74 deletions

View File

@@ -22,7 +22,7 @@ pub struct VariantAttrs {
#[darling(attributes(xml))]
pub struct EnumAttrs {
pub untagged: Flag,
pub unit_variants_name: Option<String>,
pub unit_variants_ident: Option<syn::Ident>,
}
#[derive(Default, FromDeriveInput, Clone)]

View File

@@ -2,7 +2,6 @@ use super::{attrs::EnumAttrs, Variant};
use crate::attrs::VariantAttrs;
use core::panic;
use darling::{FromDeriveInput, FromVariant};
use proc_macro2::Span;
use quote::quote;
use syn::{DataEnum, DeriveInput};
@@ -245,11 +244,11 @@ impl Enum {
if self.attrs.untagged.is_present() {
panic!("EnumUnitVariants not implemented for untagged enums");
}
let unit_enum_ident = if let Some(name) = &self.attrs.unit_variants_name {
syn::Ident::new(name, Span::call_site())
} else {
panic!("unit_variants_name not set");
};
let unit_enum_ident = self
.attrs
.unit_variants_ident
.as_ref()
.expect("unit_variants_ident no set");
let tagged_variants: Vec<_> = self
.variants
@@ -287,8 +286,15 @@ impl Enum {
quote! { #ident::#variant_ident { .. } => #unit_enum_ident::#variant_ident }
});
let str_to_unit_branches = tagged_variants.iter().map(|variant| {
let variant_ident = &variant.variant.ident;
let b_xml_name = variant.xml_name().value();
let xml_name = String::from_utf8_lossy(&b_xml_name);
quote! { #xml_name => Ok(#unit_enum_ident::#variant_ident) }
});
quote! {
enum #unit_enum_ident {
pub enum #unit_enum_ident {
#(#variant_idents),*
}
@@ -307,6 +313,17 @@ impl Enum {
}
}
}
impl ::std::str::FromStr for #unit_enum_ident {
type Err = ::rustical_xml::FromStrError;
fn from_str(val: &str) -> Result<Self, Self::Err> {
match val {
#(#str_to_unit_branches),*,
_ => Err(::rustical_xml::FromStrError)
}
}
}
}
}
}

View File

@@ -24,6 +24,9 @@ pub trait XmlRootTag {
fn root_ns_prefixes() -> HashMap<Namespace<'static>, &'static [u8]>;
}
#[derive(Debug)]
pub struct FromStrError;
pub trait EnumVariants {
const TAGGED_VARIANTS: &'static [(Option<Namespace<'static>>, &'static str)];

View File

@@ -1,3 +1,5 @@
use std::str::FromStr;
use quick_xml::name::Namespace;
use rustical_xml::EnumVariants;
use xml_derive::EnumUnitVariants;
@@ -16,7 +18,7 @@ enum ExtensionProp {
}
#[derive(EnumVariants, EnumUnitVariants)]
#[xml(unit_variants_name = "CalendarPropName")]
#[xml(unit_variants_ident = "CalendarPropName")]
enum CalendarProp {
// WebDAV (RFC 2518)
#[xml(ns = "NS_DAV")]
@@ -73,4 +75,7 @@ fn test_enum_unit_variants() {
let propname: CalendarPropName = CalendarProp::Displayname(None).into();
let displayname: (Option<Namespace>, &str) = propname.into();
assert_eq!(displayname, (Some(NS_DAV), "displayname"));
let propname: CalendarPropName = FromStr::from_str("displayname").unwrap();
assert_eq!(displayname, (Some(NS_DAV), "displayname"));
}