Implement deserialize_with for variants
Complements variant serialize_with and closes #1013.
This commit is contained in:
parent
5b815b7001
commit
9fc180e62f
@ -375,7 +375,7 @@ fn deserialize_seq(
|
|||||||
quote!(try!(_serde::de::SeqAccess::next_element::<#field_ty>(&mut __seq)))
|
quote!(try!(_serde::de::SeqAccess::next_element::<#field_ty>(&mut __seq)))
|
||||||
}
|
}
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(
|
||||||
params, field.ty, path);
|
params, field.ty, path);
|
||||||
quote!({
|
quote!({
|
||||||
#wrapper
|
#wrapper
|
||||||
@ -431,7 +431,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(params, field.ty, path);
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
quote!({
|
quote!({
|
||||||
#wrapper
|
#wrapper
|
||||||
try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value
|
try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value
|
||||||
@ -1087,6 +1087,16 @@ fn deserialize_externally_tagged_variant(
|
|||||||
variant: &Variant,
|
variant: &Variant,
|
||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
|
if let Some(path) = variant.attrs.deserialize_with() {
|
||||||
|
let (wrapper, wrapper_ty, unwrap_fn) =
|
||||||
|
wrap_deserialize_variant_with(params, &variant, path);
|
||||||
|
return quote_block! {
|
||||||
|
#wrapper
|
||||||
|
_serde::export::Result::map(
|
||||||
|
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let variant_ident = &variant.ident;
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
match variant.style {
|
match variant.style {
|
||||||
@ -1115,6 +1125,10 @@ fn deserialize_internally_tagged_variant(
|
|||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
deserializer: Tokens,
|
deserializer: Tokens,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
|
if variant.attrs.deserialize_with().is_some() {
|
||||||
|
return deserialize_untagged_variant(params, variant, cattrs, deserializer);
|
||||||
|
}
|
||||||
|
|
||||||
let variant_ident = &variant.ident;
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
match variant.style {
|
match variant.style {
|
||||||
@ -1140,6 +1154,16 @@ fn deserialize_untagged_variant(
|
|||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
deserializer: Tokens,
|
deserializer: Tokens,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
|
if let Some(path) = variant.attrs.deserialize_with() {
|
||||||
|
let (wrapper, wrapper_ty, unwrap_fn) =
|
||||||
|
wrap_deserialize_variant_with(params, &variant, path);
|
||||||
|
return quote_block! {
|
||||||
|
#wrapper
|
||||||
|
_serde::export::Result::map(
|
||||||
|
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), #unwrap_fn)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let variant_ident = &variant.ident;
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
match variant.style {
|
match variant.style {
|
||||||
@ -1201,7 +1225,7 @@ fn deserialize_externally_tagged_newtype_variant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(params, field.ty, path);
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
quote_block! {
|
quote_block! {
|
||||||
#wrapper
|
#wrapper
|
||||||
_serde::export::Result::map(
|
_serde::export::Result::map(
|
||||||
@ -1229,7 +1253,7 @@ fn deserialize_untagged_newtype_variant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(params, field.ty, path);
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||||
quote_block! {
|
quote_block! {
|
||||||
#wrapper
|
#wrapper
|
||||||
_serde::export::Result::map(
|
_serde::export::Result::map(
|
||||||
@ -1531,7 +1555,7 @@ fn deserialize_map(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(path) => {
|
Some(path) => {
|
||||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(
|
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(
|
||||||
params, field.ty, path);
|
params, field.ty, path);
|
||||||
quote!({
|
quote!({
|
||||||
#wrapper
|
#wrapper
|
||||||
@ -1664,7 +1688,7 @@ fn field_i(i: usize) -> Ident {
|
|||||||
/// in a trait to prevent it from accessing the internal `Deserialize` state.
|
/// in a trait to prevent it from accessing the internal `Deserialize` state.
|
||||||
fn wrap_deserialize_with(
|
fn wrap_deserialize_with(
|
||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
field_ty: &syn::Ty,
|
value_ty: Tokens,
|
||||||
deserialize_with: &syn::Path,
|
deserialize_with: &syn::Path,
|
||||||
) -> (Tokens, Tokens) {
|
) -> (Tokens, Tokens) {
|
||||||
let this = ¶ms.this;
|
let this = ¶ms.this;
|
||||||
@ -1672,7 +1696,7 @@ fn wrap_deserialize_with(
|
|||||||
|
|
||||||
let wrapper = quote! {
|
let wrapper = quote! {
|
||||||
struct __DeserializeWith #de_impl_generics #where_clause {
|
struct __DeserializeWith #de_impl_generics #where_clause {
|
||||||
value: #field_ty,
|
value: #value_ty,
|
||||||
phantom: _serde::export::PhantomData<#this #ty_generics>,
|
phantom: _serde::export::PhantomData<#this #ty_generics>,
|
||||||
lifetime: _serde::export::PhantomData<&'de ()>,
|
lifetime: _serde::export::PhantomData<&'de ()>,
|
||||||
}
|
}
|
||||||
@ -1695,6 +1719,68 @@ fn wrap_deserialize_with(
|
|||||||
(wrapper, wrapper_ty)
|
(wrapper, wrapper_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wrap_deserialize_field_with(
|
||||||
|
params: &Parameters,
|
||||||
|
field_ty: &syn::Ty,
|
||||||
|
deserialize_with: &syn::Path,
|
||||||
|
) -> (Tokens, Tokens) {
|
||||||
|
wrap_deserialize_with(params, quote!(#field_ty), deserialize_with)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_deserialize_variant_with(
|
||||||
|
params: &Parameters,
|
||||||
|
variant: &Variant,
|
||||||
|
deserialize_with: &syn::Path,
|
||||||
|
) -> (Tokens, Tokens, Tokens) {
|
||||||
|
let this = ¶ms.this;
|
||||||
|
let variant_ident = &variant.ident;
|
||||||
|
|
||||||
|
let field_tys = variant.fields.iter().map(|field| field.ty);
|
||||||
|
let (wrapper, wrapper_ty) =
|
||||||
|
wrap_deserialize_with(params, quote!((#(#field_tys),*)), deserialize_with);
|
||||||
|
|
||||||
|
let field_access = (0..variant.fields.len()).map(|n| Ident::new(format!("{}", n)));
|
||||||
|
let unwrap_fn = match variant.style {
|
||||||
|
Style::Struct => {
|
||||||
|
let field_idents = variant.fields.iter().map(|field| field.ident.as_ref().unwrap());
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
|__wrap| {
|
||||||
|
#this::#variant_ident { #(#field_idents: __wrap.value.#field_access),* }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Tuple => {
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
|__wrap| {
|
||||||
|
#this::#variant_ident(#(__wrap.value.#field_access),*)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Newtype => {
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
|__wrap| {
|
||||||
|
#this::#variant_ident(__wrap.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Style::Unit => {
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
|__wrap| { #this::#variant_ident }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(wrapper, wrapper_ty, unwrap_fn)
|
||||||
|
}
|
||||||
|
|
||||||
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
|
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
|
||||||
match *field.attrs.default() {
|
match *field.attrs.default() {
|
||||||
attr::Default::Default => {
|
attr::Default::Default => {
|
||||||
|
@ -130,5 +130,23 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if variant.attrs.deserialize_with().is_some() {
|
||||||
|
if variant.attrs.skip_deserializing() {
|
||||||
|
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] and \
|
||||||
|
#[serde(skip_deserializing)]", variant.ident));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, field) in variant.fields.iter().enumerate() {
|
||||||
|
if field.attrs.skip_deserializing() {
|
||||||
|
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|
||||||
|
|ident| format!("`{}`", ident));
|
||||||
|
|
||||||
|
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] \
|
||||||
|
and a field {} marked with #[serde(skip_deserializing)]",
|
||||||
|
variant.ident, ident));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2017 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||||
|
//~^ HELP: variant `Newtype` cannot have both #[serde(deserialize_with)] and a field 0 marked with #[serde(skip_deserializing)]
|
||||||
|
enum Enum {
|
||||||
|
#[serde(deserialize_with = "deserialize_some_newtype_variant")]
|
||||||
|
Newtype(#[serde(skip_deserializing)] String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_some_newtype_variant<'de, D>(_: D) -> StdResult<String, D::Error>
|
||||||
|
where D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2017 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||||
|
//~^ HELP: variant `Struct` cannot have both #[serde(deserialize_with)] and a field `f1` marked with #[serde(skip_deserializing)]
|
||||||
|
enum Enum {
|
||||||
|
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||||
|
Struct {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
f1: String,
|
||||||
|
f2: u8,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
|
||||||
|
where D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2017 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||||
|
//~^ HELP: variant `Tuple` cannot have both #[serde(deserialize_with)] and a field 0 marked with #[serde(skip_deserializing)]
|
||||||
|
enum Enum {
|
||||||
|
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||||
|
Tuple(#[serde(skip_deserializing)] String, u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
|
||||||
|
where D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2017 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||||
|
//~^ HELP: variant `Unit` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]
|
||||||
|
enum Enum {
|
||||||
|
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
Unit,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
|
||||||
|
where D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
@ -11,6 +11,7 @@ extern crate serde_derive;
|
|||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
|
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||||
|
use self::serde::de::{self, Unexpected};
|
||||||
|
|
||||||
extern crate serde_test;
|
extern crate serde_test;
|
||||||
use self::serde_test::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens,
|
use self::serde_test::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens,
|
||||||
@ -811,18 +812,22 @@ fn test_serialize_with_enum() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
enum SerializeWithVariant {
|
enum WithVariant {
|
||||||
#[serde(serialize_with="serialize_unit_variant_as_i8")]
|
#[serde(serialize_with="serialize_unit_variant_as_i8")]
|
||||||
|
#[serde(deserialize_with="deserialize_i8_as_unit_variant")]
|
||||||
Unit,
|
Unit,
|
||||||
|
|
||||||
#[serde(serialize_with="SerializeWith::serialize_with")]
|
#[serde(serialize_with="SerializeWith::serialize_with")]
|
||||||
|
#[serde(deserialize_with="DeserializeWith::deserialize_with")]
|
||||||
Newtype(i32),
|
Newtype(i32),
|
||||||
|
|
||||||
#[serde(serialize_with="serialize_some_other_variant")]
|
#[serde(serialize_with="serialize_variant_as_string")]
|
||||||
|
#[serde(deserialize_with="deserialize_string_as_variant")]
|
||||||
Tuple(String, u8),
|
Tuple(String, u8),
|
||||||
|
|
||||||
#[serde(serialize_with="serialize_some_other_variant")]
|
#[serde(serialize_with="serialize_variant_as_string")]
|
||||||
|
#[serde(deserialize_with="deserialize_string_as_variant")]
|
||||||
Struct {
|
Struct {
|
||||||
f1: String,
|
f1: String,
|
||||||
f2: u8,
|
f2: u8,
|
||||||
@ -835,7 +840,17 @@ fn serialize_unit_variant_as_i8<S>(serializer: S) -> Result<S::Ok, S::Error>
|
|||||||
serializer.serialize_i8(0)
|
serializer.serialize_i8(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_some_other_variant<S>(f1: &String,
|
fn deserialize_i8_as_unit_variant<'de, D>(deserializer: D) -> Result<(), D::Error>
|
||||||
|
where D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let n = i8::deserialize(deserializer)?;
|
||||||
|
match n {
|
||||||
|
0 => Ok(()),
|
||||||
|
_ => Err(de::Error::invalid_value(Unexpected::Signed(n as i64), &"0")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_variant_as_string<S>(f1: &String,
|
||||||
f2: &u8,
|
f2: &u8,
|
||||||
serializer: S)
|
serializer: S)
|
||||||
-> Result<S::Ok, S::Error>
|
-> Result<S::Ok, S::Error>
|
||||||
@ -844,36 +859,93 @@ fn serialize_some_other_variant<S>(f1: &String,
|
|||||||
serializer.serialize_str(format!("{};{:?}", f1, f2).as_str())
|
serializer.serialize_str(format!("{};{:?}", f1, f2).as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_string_as_variant<'de, D>(deserializer: D) -> Result<(String, u8), D::Error>
|
||||||
|
where D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s = String::deserialize(deserializer)?;
|
||||||
|
let mut pieces = s.split(';');
|
||||||
|
let f1 = match pieces.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => return Err(de::Error::invalid_length(0, &"2")),
|
||||||
|
};
|
||||||
|
let f2 = match pieces.next() {
|
||||||
|
Some(x) => x,
|
||||||
|
None => return Err(de::Error::invalid_length(1, &"2")),
|
||||||
|
};
|
||||||
|
let f2 = match f2.parse() {
|
||||||
|
Ok(n) => n,
|
||||||
|
Err(_) => {
|
||||||
|
return Err(de::Error::invalid_value(Unexpected::Str(f2), &"an 8-bit signed integer"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok((f1.into(), f2))
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialize_with_variant() {
|
fn test_serialize_with_variant() {
|
||||||
assert_ser_tokens(
|
assert_ser_tokens(
|
||||||
&SerializeWithVariant::Unit,
|
&WithVariant::Unit,
|
||||||
&[
|
&[
|
||||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Unit" },
|
Token::NewtypeVariant { name: "WithVariant", variant: "Unit" },
|
||||||
Token::I8(0),
|
Token::I8(0),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ser_tokens(
|
assert_ser_tokens(
|
||||||
&SerializeWithVariant::Newtype(123),
|
&WithVariant::Newtype(123),
|
||||||
&[
|
&[
|
||||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Newtype" },
|
Token::NewtypeVariant { name: "WithVariant", variant: "Newtype" },
|
||||||
Token::Bool(true),
|
Token::Bool(true),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ser_tokens(
|
assert_ser_tokens(
|
||||||
&SerializeWithVariant::Tuple("hello".into(), 0),
|
&WithVariant::Tuple("hello".into(), 0),
|
||||||
&[
|
&[
|
||||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Tuple" },
|
Token::NewtypeVariant { name: "WithVariant", variant: "Tuple" },
|
||||||
Token::Str("hello;0"),
|
Token::Str("hello;0"),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ser_tokens(
|
assert_ser_tokens(
|
||||||
&SerializeWithVariant::Struct { f1: "world".into(), f2: 1 },
|
&WithVariant::Struct { f1: "world".into(), f2: 1 },
|
||||||
&[
|
&[
|
||||||
Token::NewtypeVariant { name: "SerializeWithVariant", variant: "Struct" },
|
Token::NewtypeVariant { name: "WithVariant", variant: "Struct" },
|
||||||
|
Token::Str("world;1"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_with_variant() {
|
||||||
|
assert_de_tokens(
|
||||||
|
&WithVariant::Unit,
|
||||||
|
&[
|
||||||
|
Token::NewtypeVariant { name: "WithVariant", variant: "Unit" },
|
||||||
|
Token::I8(0),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&WithVariant::Newtype(123),
|
||||||
|
&[
|
||||||
|
Token::NewtypeVariant { name: "WithVariant", variant: "Newtype" },
|
||||||
|
Token::Bool(true),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&WithVariant::Tuple("hello".into(), 0),
|
||||||
|
&[
|
||||||
|
Token::NewtypeVariant { name: "WithVariant", variant: "Tuple" },
|
||||||
|
Token::Str("hello;0"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&WithVariant::Struct { f1: "world".into(), f2: 1 },
|
||||||
|
&[
|
||||||
|
Token::NewtypeVariant { name: "WithVariant", variant: "Struct" },
|
||||||
Token::Str("world;1"),
|
Token::Str("world;1"),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -374,7 +374,7 @@ fn test_gen() {
|
|||||||
s: vis::S,
|
s: vis::S,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum ExternallyTaggedVariantWith {
|
enum ExternallyTaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Normal { f1: String },
|
Normal { f1: String },
|
||||||
@ -404,7 +404,7 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
assert_ser::<ExternallyTaggedVariantWith>();
|
assert_ser::<ExternallyTaggedVariantWith>();
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(tag = "t")]
|
#[serde(tag = "t")]
|
||||||
enum InternallyTaggedVariantWith {
|
enum InternallyTaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -430,7 +430,7 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
assert_ser::<InternallyTaggedVariantWith>();
|
assert_ser::<InternallyTaggedVariantWith>();
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(tag = "t", content = "c")]
|
#[serde(tag = "t", content = "c")]
|
||||||
enum AdjacentlyTaggedVariantWith {
|
enum AdjacentlyTaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -461,7 +461,7 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
assert_ser::<AdjacentlyTaggedVariantWith>();
|
assert_ser::<AdjacentlyTaggedVariantWith>();
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum UntaggedVariantWith {
|
enum UntaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
Loading…
Reference in New Issue
Block a user