Implement skip_serializing for enum variant
This commit is contained in:
parent
2c984980a0
commit
2fea8c9c28
@ -255,77 +255,123 @@ fn serialize_variant(
|
|||||||
|
|
||||||
let variant_ident = variant.ident.clone();
|
let variant_ident = variant.ident.clone();
|
||||||
let variant_name = variant.attrs.name().serialize_name();
|
let variant_name = variant.attrs.name().serialize_name();
|
||||||
|
let skipped_err = quote! {
|
||||||
|
Err(_serde::ser::Error::invalid_value("The enum variant was skipped for serialization"))
|
||||||
|
};
|
||||||
|
|
||||||
match variant.style {
|
if variant.attrs.skip_serializing() {
|
||||||
Style::Unit => {
|
match variant.style {
|
||||||
quote! {
|
Style::Unit => {
|
||||||
#type_ident::#variant_ident =>
|
quote! {
|
||||||
_serde::ser::Serializer::serialize_unit_variant(
|
#type_ident::#variant_ident => #skipped_err,
|
||||||
_serializer,
|
}
|
||||||
#type_name,
|
},
|
||||||
#variant_index,
|
Style::Newtype => {
|
||||||
#variant_name,
|
quote! {
|
||||||
),
|
#type_ident::#variant_ident(ref __simple_value) => #skipped_err,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Style::Newtype => {
|
Style::Tuple => {
|
||||||
let block = serialize_newtype_variant(
|
let field_names: Vec<Tokens> = (0 .. variant.fields.len())
|
||||||
type_name,
|
.map(|i| {
|
||||||
variant_index,
|
let id = aster::id(format!("__field{}", i));
|
||||||
variant_name,
|
quote!(ref #id)
|
||||||
ty,
|
})
|
||||||
generics,
|
.collect();
|
||||||
&variant.fields[0],
|
|
||||||
);
|
|
||||||
|
|
||||||
quote! {
|
let pat = quote!(#type_ident::#variant_ident(#(#field_names),*));
|
||||||
#type_ident::#variant_ident(ref __simple_value) => #block,
|
|
||||||
|
quote! {
|
||||||
|
#pat => #skipped_err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
Style::Struct => {
|
||||||
Style::Tuple => {
|
let fields = variant.fields.iter().map(|field| {
|
||||||
let field_names: Vec<Tokens> = (0 .. variant.fields.len())
|
let id = match field.ident {
|
||||||
.map(|i| {
|
Some(ref name) => name.clone(),
|
||||||
let id = aster::id(format!("__field{}", i));
|
None => panic!("struct variant has unnamed fields"),
|
||||||
|
};
|
||||||
quote!(ref #id)
|
quote!(ref #id)
|
||||||
})
|
});
|
||||||
.collect();
|
let pat = quote!(#type_ident::#variant_ident { #(#fields),* });
|
||||||
|
|
||||||
let pat = quote!(#type_ident::#variant_ident(#(#field_names),*));
|
quote! {
|
||||||
|
#pat => #skipped_err,
|
||||||
let block = serialize_tuple_variant(
|
}
|
||||||
type_name,
|
|
||||||
variant_index,
|
|
||||||
variant_name,
|
|
||||||
generics,
|
|
||||||
ty,
|
|
||||||
&variant.fields,
|
|
||||||
);
|
|
||||||
|
|
||||||
quote! {
|
|
||||||
#pat => { #block }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Style::Struct => {
|
} else { // variant wasn't skipped
|
||||||
let fields = variant.fields.iter().map(|field| {
|
match variant.style {
|
||||||
let id = match field.ident {
|
Style::Unit => {
|
||||||
Some(ref name) => name.clone(),
|
quote! {
|
||||||
None => panic!("struct variant has unnamed fields"),
|
#type_ident::#variant_ident =>
|
||||||
};
|
_serde::ser::Serializer::serialize_unit_variant(
|
||||||
quote!(ref #id)
|
_serializer,
|
||||||
});
|
#type_name,
|
||||||
let pat = quote!(#type_ident::#variant_ident { #(#fields),* });
|
#variant_index,
|
||||||
|
#variant_name,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Style::Newtype => {
|
||||||
|
let block = serialize_newtype_variant(
|
||||||
|
type_name,
|
||||||
|
variant_index,
|
||||||
|
variant_name,
|
||||||
|
ty,
|
||||||
|
generics,
|
||||||
|
&variant.fields[0],
|
||||||
|
);
|
||||||
|
|
||||||
let block = serialize_struct_variant(
|
quote! {
|
||||||
variant_index,
|
#type_ident::#variant_ident(ref __simple_value) => #block,
|
||||||
variant_name,
|
}
|
||||||
generics,
|
},
|
||||||
ty,
|
Style::Tuple => {
|
||||||
&variant.fields,
|
let field_names: Vec<Tokens> = (0 .. variant.fields.len())
|
||||||
item_attrs,
|
.map(|i| {
|
||||||
);
|
let id = aster::id(format!("__field{}", i));
|
||||||
|
quote!(ref #id)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
quote! {
|
let pat = quote!(#type_ident::#variant_ident(#(#field_names),*));
|
||||||
#pat => { #block }
|
|
||||||
|
let block = serialize_tuple_variant(
|
||||||
|
type_name,
|
||||||
|
variant_index,
|
||||||
|
variant_name,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
&variant.fields,
|
||||||
|
);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#pat => { #block }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Struct => {
|
||||||
|
let fields = variant.fields.iter().map(|field| {
|
||||||
|
let id = match field.ident {
|
||||||
|
Some(ref name) => name.clone(),
|
||||||
|
None => panic!("struct variant has unnamed fields"),
|
||||||
|
};
|
||||||
|
quote!(ref #id)
|
||||||
|
});
|
||||||
|
let pat = quote!(#type_ident::#variant_ident { #(#fields),* });
|
||||||
|
|
||||||
|
let block = serialize_struct_variant(
|
||||||
|
variant_index,
|
||||||
|
variant_name,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
&variant.fields,
|
||||||
|
item_attrs,
|
||||||
|
);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#pat => { #block }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,7 @@ impl Item {
|
|||||||
pub struct Variant {
|
pub struct Variant {
|
||||||
name: Name,
|
name: Name,
|
||||||
skip_deserializing: bool,
|
skip_deserializing: bool,
|
||||||
|
skip_serializing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variant {
|
impl Variant {
|
||||||
@ -195,6 +196,7 @@ impl Variant {
|
|||||||
let mut ser_name = Attr::none(cx, "rename");
|
let mut ser_name = Attr::none(cx, "rename");
|
||||||
let mut de_name = Attr::none(cx, "rename");
|
let mut de_name = Attr::none(cx, "rename");
|
||||||
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
|
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
|
||||||
|
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
||||||
|
|
||||||
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
|
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
|
||||||
for meta_item in meta_items {
|
for meta_item in meta_items {
|
||||||
@ -218,6 +220,10 @@ impl Variant {
|
|||||||
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
|
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
|
||||||
skip_deserializing.set_true();
|
skip_deserializing.set_true();
|
||||||
}
|
}
|
||||||
|
// Parse `#[serde(skip_serializing)]`
|
||||||
|
MetaItem(Word(ref name)) if name == "skip_serializing" => {
|
||||||
|
skip_serializing.set_true();
|
||||||
|
}
|
||||||
|
|
||||||
MetaItem(ref meta_item) => {
|
MetaItem(ref meta_item) => {
|
||||||
cx.error(format!("unknown serde variant attribute `{}`",
|
cx.error(format!("unknown serde variant attribute `{}`",
|
||||||
@ -237,6 +243,7 @@ impl Variant {
|
|||||||
deserialize: de_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(),
|
skip_deserializing: skip_deserializing.get(),
|
||||||
|
skip_serializing: skip_serializing.get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +254,10 @@ impl Variant {
|
|||||||
pub fn skip_deserializing(&self) -> bool {
|
pub fn skip_deserializing(&self) -> bool {
|
||||||
self.skip_deserializing
|
self.skip_deserializing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn skip_serializing(&self) -> bool {
|
||||||
|
self.skip_serializing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents field attribute information
|
/// Represents field attribute information
|
||||||
|
@ -30,12 +30,20 @@ struct Struct {
|
|||||||
c: i32,
|
c: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, PartialEq, Debug)]
|
||||||
enum Enum {
|
enum Enum {
|
||||||
Unit,
|
Unit,
|
||||||
One(i32),
|
One(i32),
|
||||||
Seq(i32, i32),
|
Seq(i32, i32),
|
||||||
Map { a: i32, b: i32 },
|
Map { a: i32, b: i32 },
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedUnit,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedOne(i32),
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedSeq(i32, i32),
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedMap { _a: i32, _b: i32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -388,3 +396,23 @@ fn test_cannot_serialize_paths() {
|
|||||||
&[],
|
&[],
|
||||||
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
|
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_enum_skipped() {
|
||||||
|
assert_ser_tokens_error(
|
||||||
|
&Enum::SkippedUnit,
|
||||||
|
&[],
|
||||||
|
Error::InvalidValue("The enum variant was skipped for serialization".to_owned()));
|
||||||
|
assert_ser_tokens_error(
|
||||||
|
&Enum::SkippedOne(42),
|
||||||
|
&[],
|
||||||
|
Error::InvalidValue("The enum variant was skipped for serialization".to_owned()));
|
||||||
|
assert_ser_tokens_error(
|
||||||
|
&Enum::SkippedSeq(1, 2),
|
||||||
|
&[],
|
||||||
|
Error::InvalidValue("The enum variant was skipped for serialization".to_owned()));
|
||||||
|
assert_ser_tokens_error(
|
||||||
|
&Enum::SkippedMap { _a: 1, _b: 2 },
|
||||||
|
&[],
|
||||||
|
Error::InvalidValue("The enum variant was skipped for serialization".to_owned()));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user