diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 93d7d6cf..877b6a05 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -496,6 +496,7 @@ fn deserialize_item_enum( let variant_visitor = deserialize_field_visitor( variants.iter() + .filter(|variant| !variant.attrs.skip_deserializing()) .map(|variant| variant.attrs.name().deserialize_name()) .collect(), item_attrs, @@ -518,7 +519,7 @@ fn deserialize_item_enum( // Match arms to extract a variant from a string let mut variant_arms = vec![]; - for (i, variant) in variants.iter().enumerate() { + for (i, variant) in variants.iter().filter(|variant| !variant.attrs.skip_deserializing()).enumerate() { let variant_name = aster::id(format!("__field{}", i)); let variant_name = quote!(__Field::#variant_name); diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 124592dc..a9a69169 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -187,12 +187,14 @@ impl Item { #[derive(Debug)] pub struct Variant { name: Name, + skip_deserializing: bool, } impl Variant { pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); + let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { @@ -212,6 +214,10 @@ impl Variant { de_name.set_opt(de); } } + // Parse `#[serde(skip_deserializing)]` + MetaItem(Word(ref name)) if name == "skip_deserializing" => { + skip_deserializing.set_true(); + } MetaItem(ref meta_item) => { cx.error(format!("unknown serde variant attribute `{}`", @@ -230,12 +236,17 @@ impl Variant { serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()), deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()), }, + skip_deserializing: skip_deserializing.get(), } } pub fn name(&self) -> &Name { &self.name } + + pub fn skip_deserializing(&self) -> bool { + self.skip_deserializing + } } /// Represents field attribute information diff --git a/testing/tests/test_de.rs b/testing/tests/test_de.rs index 56fb1cee..e929d3a1 100644 --- a/testing/tests/test_de.rs +++ b/testing/tests/test_de.rs @@ -37,7 +37,9 @@ enum Enum { Unit, Simple(i32), Seq(i32, i32, i32), - Map { a: i32, b: i32, c: i32 } + Map { a: i32, b: i32, c: i32 }, + #[serde(skip_deserializing)] + Skipped, } ////////////////////////////////////////////////////////////////////////// @@ -805,6 +807,12 @@ declare_error_tests! { ], Error::UnknownVariant("Foo".to_owned()), } + test_enum_skipped_variant { + &[ + Token::EnumUnit("Enum", "Skipped"), + ], + Error::UnknownVariant("Skipped".to_owned()), + } test_struct_seq_too_long { &[ Token::SeqStart(Some(4)),