From a35bde49c6409b05136f5f2383ac836c1ffb665d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 14 Apr 2017 16:14:03 -0700 Subject: [PATCH] Factor out logic to decide the tag style --- serde_derive_internals/src/attr.rs | 102 ++++++++++++++++------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/serde_derive_internals/src/attr.rs b/serde_derive_internals/src/attr.rs index 4f08e1b5..1af148d0 100644 --- a/serde_derive_internals/src/attr.rs +++ b/serde_derive_internals/src/attr.rs @@ -319,52 +319,6 @@ impl Container { } } - let tag = match (untagged.get(), internal_tag.get(), content.get()) { - (false, None, None) => EnumTag::External, - (true, None, None) => EnumTag::None, - (false, Some(tag), None) => { - // Check that there are no tuple variants. - if let syn::Body::Enum(ref variants) = item.body { - for variant in variants { - match variant.data { - syn::VariantData::Struct(_) | - syn::VariantData::Unit => {} - syn::VariantData::Tuple(ref fields) => { - if fields.len() != 1 { - cx.error("#[serde(tag = \"...\")] cannot be used with tuple \ - variants"); - break; - } - } - } - } - } - EnumTag::Internal { tag: tag } - } - (true, Some(_), None) => { - cx.error("enum cannot be both untagged and internally tagged"); - EnumTag::External // doesn't matter, will error - } - (false, None, Some(_)) => { - cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together"); - EnumTag::External - } - (true, None, Some(_)) => { - cx.error("untagged enum cannot have #[serde(content = \"...\")]"); - EnumTag::External - } - (false, Some(tag), Some(content)) => { - EnumTag::Adjacent { - tag: tag, - content: content, - } - } - (true, Some(_), Some(_)) => { - cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"); - EnumTag::External - } - }; - Container { name: Name { serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), @@ -375,7 +329,7 @@ impl Container { rename_all: rename_all.get().unwrap_or(RenameRule::None), ser_bound: ser_bound.get(), de_bound: de_bound.get(), - tag: tag, + tag: decide_tag(cx, item, untagged, internal_tag, content), from_type: from_type.get(), into_type: into_type.get(), remote: remote.get(), @@ -423,6 +377,60 @@ impl Container { } } +fn decide_tag( + cx: &Ctxt, + item: &syn::MacroInput, + untagged: BoolAttr, + internal_tag: Attr, + content: Attr, +) -> EnumTag { + match (untagged.get(), internal_tag.get(), content.get()) { + (false, None, None) => EnumTag::External, + (true, None, None) => EnumTag::None, + (false, Some(tag), None) => { + // Check that there are no tuple variants. + if let syn::Body::Enum(ref variants) = item.body { + for variant in variants { + match variant.data { + syn::VariantData::Struct(_) | + syn::VariantData::Unit => {} + syn::VariantData::Tuple(ref fields) => { + if fields.len() != 1 { + cx.error("#[serde(tag = \"...\")] cannot be used with tuple \ + variants"); + break; + } + } + } + } + } + EnumTag::Internal { tag: tag } + } + (true, Some(_), None) => { + cx.error("enum cannot be both untagged and internally tagged"); + EnumTag::External // doesn't matter, will error + } + (false, None, Some(_)) => { + cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together"); + EnumTag::External + } + (true, None, Some(_)) => { + cx.error("untagged enum cannot have #[serde(content = \"...\")]"); + EnumTag::External + } + (false, Some(tag), Some(content)) => { + EnumTag::Adjacent { + tag: tag, + content: content, + } + } + (true, Some(_), Some(_)) => { + cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"); + EnumTag::External + } + } +} + /// Represents variant attribute information #[derive(Debug)] pub struct Variant {