mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-23 18:51:04 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2591e9b39 | |||
| 8ce0dee6da | |||
| 16daba8ea9 | |||
| 8b4074ee77 | |||
| 85fbd8793a | |||
| 65705e2091 | |||
| 385a385c62 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.81" # remember to update html_root_url
|
version = "1.0.82" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
|
|||||||
+1
-1
@@ -75,7 +75,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.81")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.82")]
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.81" # remember to update html_root_url
|
version = "1.0.82" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
|
|||||||
+27
-8
@@ -89,7 +89,10 @@ fn precondition_sized(cx: &Ctxt, cont: &Container) {
|
|||||||
if let Data::Struct(_, ref fields) = cont.data {
|
if let Data::Struct(_, ref fields) = cont.data {
|
||||||
if let Some(last) = fields.last() {
|
if let Some(last) = fields.last() {
|
||||||
if let syn::Type::Slice(_) = *last.ty {
|
if let syn::Type::Slice(_) = *last.ty {
|
||||||
cx.error_spanned_by(cont.original, "cannot deserialize a dynamically sized struct");
|
cx.error_spanned_by(
|
||||||
|
cont.original,
|
||||||
|
"cannot deserialize a dynamically sized struct",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,7 +369,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
|||||||
None => {
|
None => {
|
||||||
let span = transparent_field.original.span();
|
let span = transparent_field.original.span();
|
||||||
quote_spanned!(span=> _serde::Deserialize::deserialize)
|
quote_spanned!(span=> _serde::Deserialize::deserialize)
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let assign = fields.iter().map(|field| {
|
let assign = fields.iter().map(|field| {
|
||||||
@@ -661,11 +664,18 @@ fn deserialize_seq(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let value_if_none = match *field.attrs.default() {
|
||||||
|
attr::Default::Default => quote!(_serde::export::Default::default()),
|
||||||
|
attr::Default::Path(ref path) => quote!(#path()),
|
||||||
|
attr::Default::None => quote!(
|
||||||
|
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
|
||||||
|
),
|
||||||
|
};
|
||||||
let assign = quote! {
|
let assign = quote! {
|
||||||
let #var = match #visit {
|
let #var = match #visit {
|
||||||
_serde::export::Some(__value) => __value,
|
_serde::export::Some(__value) => __value,
|
||||||
_serde::export::None => {
|
_serde::export::None => {
|
||||||
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
|
#value_if_none
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -740,8 +750,16 @@ fn deserialize_seq_in_place(
|
|||||||
self.place.#member = #default;
|
self.place.#member = #default;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let return_invalid_length = quote! {
|
let value_if_none = match *field.attrs.default() {
|
||||||
|
attr::Default::Default => quote!(
|
||||||
|
self.place.#member = _serde::export::Default::default();
|
||||||
|
),
|
||||||
|
attr::Default::Path(ref path) => quote!(
|
||||||
|
self.place.#member = #path();
|
||||||
|
),
|
||||||
|
attr::Default::None => quote!(
|
||||||
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
|
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
|
||||||
|
),
|
||||||
};
|
};
|
||||||
let write = match field.attrs.deserialize_with() {
|
let write = match field.attrs.deserialize_with() {
|
||||||
None => {
|
None => {
|
||||||
@@ -749,7 +767,7 @@ fn deserialize_seq_in_place(
|
|||||||
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
||||||
_serde::private::de::InPlaceSeed(&mut self.place.#member)))
|
_serde::private::de::InPlaceSeed(&mut self.place.#member)))
|
||||||
{
|
{
|
||||||
#return_invalid_length
|
#value_if_none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -762,7 +780,7 @@ fn deserialize_seq_in_place(
|
|||||||
self.place.#member = __wrap.value;
|
self.place.#member = __wrap.value;
|
||||||
}
|
}
|
||||||
_serde::export::None => {
|
_serde::export::None => {
|
||||||
#return_invalid_length
|
#value_if_none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1815,7 +1833,8 @@ fn deserialize_externally_tagged_newtype_variant(
|
|||||||
None => {
|
None => {
|
||||||
let field_ty = field.ty;
|
let field_ty = field.ty;
|
||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
let func = quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
|
let func =
|
||||||
|
quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
|
||||||
quote_expr! {
|
quote_expr! {
|
||||||
_serde::export::Result::map(#func(__variant), #this::#variant_ident)
|
_serde::export::Result::map(#func(__variant), #this::#variant_ident)
|
||||||
}
|
}
|
||||||
@@ -2455,7 +2474,7 @@ fn deserialize_map(
|
|||||||
None => {
|
None => {
|
||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
quote_spanned!(span=> _serde::de::Deserialize::deserialize)
|
quote_spanned!(span=> _serde::de::Deserialize::deserialize)
|
||||||
},
|
}
|
||||||
Some(path) => quote!(#path),
|
Some(path) => quote!(#path),
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
|
|||||||
@@ -60,7 +60,11 @@ pub enum Style {
|
|||||||
|
|
||||||
impl<'a> Container<'a> {
|
impl<'a> Container<'a> {
|
||||||
/// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`.
|
/// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`.
|
||||||
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive) -> Option<Container<'a>> {
|
pub fn from_ast(
|
||||||
|
cx: &Ctxt,
|
||||||
|
item: &'a syn::DeriveInput,
|
||||||
|
derive: Derive,
|
||||||
|
) -> Option<Container<'a>> {
|
||||||
let mut attrs = attr::Container::from_ast(cx, item);
|
let mut attrs = attr::Container::from_ast(cx, item);
|
||||||
|
|
||||||
let mut data = match item.data {
|
let mut data = match item.data {
|
||||||
|
|||||||
@@ -42,10 +42,8 @@ impl<'c, T> Attr<'c, T> {
|
|||||||
let tokens = obj.into_token_stream();
|
let tokens = obj.into_token_stream();
|
||||||
|
|
||||||
if self.value.is_some() {
|
if self.value.is_some() {
|
||||||
self.cx.error_spanned_by(
|
self.cx
|
||||||
tokens,
|
.error_spanned_by(tokens, format!("duplicate serde attribute `{}`", self.name));
|
||||||
format!("duplicate serde attribute `{}`", self.name),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
self.tokens = tokens;
|
self.tokens = tokens;
|
||||||
self.value = Some(value);
|
self.value = Some(value);
|
||||||
@@ -232,11 +230,14 @@ impl Container {
|
|||||||
if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
|
if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
|
||||||
match RenameRule::from_str(&s.value()) {
|
match RenameRule::from_str(&s.value()) {
|
||||||
Ok(rename_rule) => rename_all.set(&m.ident, rename_rule),
|
Ok(rename_rule) => rename_all.set(&m.ident, rename_rule),
|
||||||
Err(()) => cx.error_spanned_by(s, format!(
|
Err(()) => cx.error_spanned_by(
|
||||||
|
s,
|
||||||
|
format!(
|
||||||
"unknown rename rule for #[serde(rename_all \
|
"unknown rename rule for #[serde(rename_all \
|
||||||
= {:?})]",
|
= {:?})]",
|
||||||
s.value(),
|
s.value(),
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,14 +262,17 @@ impl Container {
|
|||||||
fields,
|
fields,
|
||||||
"#[serde(default)] can only be used on structs \
|
"#[serde(default)] can only be used on structs \
|
||||||
with named fields",
|
with named fields",
|
||||||
)
|
),
|
||||||
},
|
},
|
||||||
syn::Data::Enum(syn::DataEnum { ref enum_token, .. }) => cx.error_spanned_by(
|
syn::Data::Enum(syn::DataEnum { ref enum_token, .. }) => cx
|
||||||
|
.error_spanned_by(
|
||||||
enum_token,
|
enum_token,
|
||||||
"#[serde(default)] can only be used on structs \
|
"#[serde(default)] can only be used on structs \
|
||||||
with named fields",
|
with named fields",
|
||||||
),
|
),
|
||||||
syn::Data::Union(syn::DataUnion { ref union_token, .. }) => cx.error_spanned_by(
|
syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}) => cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(default)] can only be used on structs \
|
"#[serde(default)] can only be used on structs \
|
||||||
with named fields",
|
with named fields",
|
||||||
@@ -279,22 +283,28 @@ impl Container {
|
|||||||
Meta(NameValue(ref m)) if m.ident == "default" => {
|
Meta(NameValue(ref m)) if m.ident == "default" => {
|
||||||
if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
|
if let Ok(path) = parse_lit_into_expr_path(cx, &m.ident, &m.lit) {
|
||||||
match item.data {
|
match item.data {
|
||||||
syn::Data::Struct(syn::DataStruct { ref fields, .. }) => match *fields {
|
syn::Data::Struct(syn::DataStruct { ref fields, .. }) => {
|
||||||
|
match *fields {
|
||||||
syn::Fields::Named(_) => {
|
syn::Fields::Named(_) => {
|
||||||
default.set(&m.ident, Default::Path(path));
|
default.set(&m.ident, Default::Path(path));
|
||||||
}
|
}
|
||||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => cx.error_spanned_by(
|
syn::Fields::Unnamed(_) | syn::Fields::Unit => cx
|
||||||
|
.error_spanned_by(
|
||||||
fields,
|
fields,
|
||||||
"#[serde(default = \"...\")] can only be used \
|
"#[serde(default = \"...\")] can only be used \
|
||||||
on structs with named fields",
|
on structs with named fields",
|
||||||
)
|
),
|
||||||
},
|
}
|
||||||
syn::Data::Enum(syn::DataEnum { ref enum_token, .. }) => cx.error_spanned_by(
|
}
|
||||||
|
syn::Data::Enum(syn::DataEnum { ref enum_token, .. }) => cx
|
||||||
|
.error_spanned_by(
|
||||||
enum_token,
|
enum_token,
|
||||||
"#[serde(default = \"...\")] can only be used \
|
"#[serde(default = \"...\")] can only be used \
|
||||||
on structs with named fields",
|
on structs with named fields",
|
||||||
),
|
),
|
||||||
syn::Data::Union(syn::DataUnion { ref union_token, .. }) => cx.error_spanned_by(
|
syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}) => cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(default = \"...\")] can only be used \
|
"#[serde(default = \"...\")] can only be used \
|
||||||
on structs with named fields",
|
on structs with named fields",
|
||||||
@@ -326,13 +336,17 @@ impl Container {
|
|||||||
syn::Data::Enum(_) => {
|
syn::Data::Enum(_) => {
|
||||||
untagged.set_true(word);
|
untagged.set_true(word);
|
||||||
}
|
}
|
||||||
syn::Data::Struct(syn::DataStruct { ref struct_token, .. }) => {
|
syn::Data::Struct(syn::DataStruct {
|
||||||
|
ref struct_token, ..
|
||||||
|
}) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
struct_token,
|
struct_token,
|
||||||
"#[serde(untagged)] can only be used on enums",
|
"#[serde(untagged)] can only be used on enums",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
syn::Data::Union(syn::DataUnion { ref union_token, .. }) => {
|
syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(untagged)] can only be used on enums",
|
"#[serde(untagged)] can only be used on enums",
|
||||||
@@ -347,18 +361,22 @@ impl Container {
|
|||||||
syn::Data::Enum(_) => {
|
syn::Data::Enum(_) => {
|
||||||
internal_tag.set(&m.ident, s.value());
|
internal_tag.set(&m.ident, s.value());
|
||||||
}
|
}
|
||||||
syn::Data::Struct(syn::DataStruct { ref struct_token, .. }) => {
|
syn::Data::Struct(syn::DataStruct {
|
||||||
|
ref struct_token, ..
|
||||||
|
}) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
struct_token,
|
struct_token,
|
||||||
"#[serde(tag = \"...\")] can only be used on enums",
|
"#[serde(tag = \"...\")] can only be used on enums",
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
syn::Data::Union(syn::DataUnion { ref union_token, .. }) => {
|
syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(tag = \"...\")] can only be used on enums",
|
"#[serde(tag = \"...\")] can only be used on enums",
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,18 +388,22 @@ impl Container {
|
|||||||
syn::Data::Enum(_) => {
|
syn::Data::Enum(_) => {
|
||||||
content.set(&m.ident, s.value());
|
content.set(&m.ident, s.value());
|
||||||
}
|
}
|
||||||
syn::Data::Struct(syn::DataStruct { ref struct_token, .. }) => {
|
syn::Data::Struct(syn::DataStruct {
|
||||||
|
ref struct_token, ..
|
||||||
|
}) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
struct_token,
|
struct_token,
|
||||||
"#[serde(content = \"...\")] can only be used on enums",
|
"#[serde(content = \"...\")] can only be used on enums",
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
syn::Data::Union(syn::DataUnion { ref union_token, .. }) => {
|
syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(content = \"...\")] can only be used on enums",
|
"#[serde(content = \"...\")] can only be used on enums",
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,10 +444,10 @@ impl Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Meta(ref meta_item) => {
|
Meta(ref meta_item) => {
|
||||||
cx.error_spanned_by(meta_item.name(), format!(
|
cx.error_spanned_by(
|
||||||
"unknown serde container attribute `{}`",
|
meta_item.name(),
|
||||||
meta_item.name()
|
format!("unknown serde container attribute `{}`", meta_item.name()),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal(ref lit) => {
|
Literal(ref lit) => {
|
||||||
@@ -519,7 +541,11 @@ fn decide_tag(
|
|||||||
internal_tag: Attr<String>,
|
internal_tag: Attr<String>,
|
||||||
content: Attr<String>,
|
content: Attr<String>,
|
||||||
) -> EnumTag {
|
) -> EnumTag {
|
||||||
match (untagged.0.get_with_tokens(), internal_tag.get_with_tokens(), content.get_with_tokens()) {
|
match (
|
||||||
|
untagged.0.get_with_tokens(),
|
||||||
|
internal_tag.get_with_tokens(),
|
||||||
|
content.get_with_tokens(),
|
||||||
|
) {
|
||||||
(None, None, None) => EnumTag::External,
|
(None, None, None) => EnumTag::External,
|
||||||
(Some(_), None, None) => EnumTag::None,
|
(Some(_), None, None) => EnumTag::None,
|
||||||
(None, Some((_, tag)), None) => {
|
(None, Some((_, tag)), None) => {
|
||||||
@@ -600,7 +626,11 @@ fn decide_identifier(
|
|||||||
field_identifier: BoolAttr,
|
field_identifier: BoolAttr,
|
||||||
variant_identifier: BoolAttr,
|
variant_identifier: BoolAttr,
|
||||||
) -> Identifier {
|
) -> Identifier {
|
||||||
match (&item.data, field_identifier.0.get_with_tokens(), variant_identifier.0.get_with_tokens()) {
|
match (
|
||||||
|
&item.data,
|
||||||
|
field_identifier.0.get_with_tokens(),
|
||||||
|
variant_identifier.0.get_with_tokens(),
|
||||||
|
) {
|
||||||
(_, None, None) => Identifier::No,
|
(_, None, None) => Identifier::No,
|
||||||
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
|
(_, Some((field_identifier_tokens, _)), Some((variant_identifier_tokens, _))) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
@@ -615,28 +645,52 @@ fn decide_identifier(
|
|||||||
}
|
}
|
||||||
(&syn::Data::Enum(_), Some(_), None) => Identifier::Field,
|
(&syn::Data::Enum(_), Some(_), None) => Identifier::Field,
|
||||||
(&syn::Data::Enum(_), None, Some(_)) => Identifier::Variant,
|
(&syn::Data::Enum(_), None, Some(_)) => Identifier::Variant,
|
||||||
(&syn::Data::Struct(syn::DataStruct { ref struct_token, .. }), Some(_), None) => {
|
(
|
||||||
|
&syn::Data::Struct(syn::DataStruct {
|
||||||
|
ref struct_token, ..
|
||||||
|
}),
|
||||||
|
Some(_),
|
||||||
|
None,
|
||||||
|
) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
struct_token,
|
struct_token,
|
||||||
"#[serde(field_identifier)] can only be used on an enum",
|
"#[serde(field_identifier)] can only be used on an enum",
|
||||||
);
|
);
|
||||||
Identifier::No
|
Identifier::No
|
||||||
}
|
}
|
||||||
(&syn::Data::Union(syn::DataUnion { ref union_token, .. }), Some(_), None) => {
|
(
|
||||||
|
&syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}),
|
||||||
|
Some(_),
|
||||||
|
None,
|
||||||
|
) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(field_identifier)] can only be used on an enum",
|
"#[serde(field_identifier)] can only be used on an enum",
|
||||||
);
|
);
|
||||||
Identifier::No
|
Identifier::No
|
||||||
}
|
}
|
||||||
(&syn::Data::Struct(syn::DataStruct { ref struct_token, .. }), None, Some(_)) => {
|
(
|
||||||
|
&syn::Data::Struct(syn::DataStruct {
|
||||||
|
ref struct_token, ..
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
Some(_),
|
||||||
|
) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
struct_token,
|
struct_token,
|
||||||
"#[serde(variant_identifier)] can only be used on an enum",
|
"#[serde(variant_identifier)] can only be used on an enum",
|
||||||
);
|
);
|
||||||
Identifier::No
|
Identifier::No
|
||||||
}
|
}
|
||||||
(&syn::Data::Union(syn::DataUnion { ref union_token, .. }), None, Some(_)) => {
|
(
|
||||||
|
&syn::Data::Union(syn::DataUnion {
|
||||||
|
ref union_token, ..
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
Some(_),
|
||||||
|
) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(
|
||||||
union_token,
|
union_token,
|
||||||
"#[serde(variant_identifier)] can only be used on an enum",
|
"#[serde(variant_identifier)] can only be used on an enum",
|
||||||
@@ -700,11 +754,14 @@ impl Variant {
|
|||||||
if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
|
if let Ok(s) = get_lit_str(cx, &m.ident, &m.ident, &m.lit) {
|
||||||
match RenameRule::from_str(&s.value()) {
|
match RenameRule::from_str(&s.value()) {
|
||||||
Ok(rename_rule) => rename_all.set(&m.ident, rename_rule),
|
Ok(rename_rule) => rename_all.set(&m.ident, rename_rule),
|
||||||
Err(()) => cx.error_spanned_by(s, format!(
|
Err(()) => cx.error_spanned_by(
|
||||||
|
s,
|
||||||
|
format!(
|
||||||
"unknown rename rule for #[serde(rename_all \
|
"unknown rename rule for #[serde(rename_all \
|
||||||
= {:?})]",
|
= {:?})]",
|
||||||
s.value()
|
s.value()
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -794,17 +851,14 @@ impl Variant {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Meta(ref meta_item) => {
|
Meta(ref meta_item) => {
|
||||||
cx.error_spanned_by(meta_item.name(), format!(
|
cx.error_spanned_by(
|
||||||
"unknown serde variant attribute `{}`",
|
meta_item.name(),
|
||||||
meta_item.name()
|
format!("unknown serde variant attribute `{}`", meta_item.name()),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal(ref lit) => {
|
Literal(ref lit) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(lit, "unexpected literal in serde variant attribute");
|
||||||
lit,
|
|
||||||
"unexpected literal in serde variant attribute",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1071,10 +1125,13 @@ impl Field {
|
|||||||
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
|
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) {
|
||||||
for lifetime in &lifetimes {
|
for lifetime in &lifetimes {
|
||||||
if !borrowable.contains(lifetime) {
|
if !borrowable.contains(lifetime) {
|
||||||
cx.error_spanned_by(field, format!(
|
cx.error_spanned_by(
|
||||||
|
field,
|
||||||
|
format!(
|
||||||
"field `{}` does not have lifetime {}",
|
"field `{}` does not have lifetime {}",
|
||||||
ident, lifetime
|
ident, lifetime
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
borrowed_lifetimes.set(&m.ident, lifetimes);
|
borrowed_lifetimes.set(&m.ident, lifetimes);
|
||||||
@@ -1095,17 +1152,14 @@ impl Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Meta(ref meta_item) => {
|
Meta(ref meta_item) => {
|
||||||
cx.error_spanned_by(meta_item.name(), format!(
|
cx.error_spanned_by(
|
||||||
"unknown serde field attribute `{}`",
|
meta_item.name(),
|
||||||
meta_item.name()
|
format!("unknown serde field attribute `{}`", meta_item.name()),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal(ref lit) => {
|
Literal(ref lit) => {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(lit, "unexpected literal in serde field attribute");
|
||||||
lit,
|
|
||||||
"unexpected literal in serde field attribute",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1299,11 +1353,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
cx.error_spanned_by(meta, format!(
|
cx.error_spanned_by(
|
||||||
|
meta,
|
||||||
|
format!(
|
||||||
"malformed {0} attribute, expected `{0}(serialize = ..., \
|
"malformed {0} attribute, expected `{0}(serialize = ..., \
|
||||||
deserialize = ...)`",
|
deserialize = ...)`",
|
||||||
attr_name
|
attr_name
|
||||||
));
|
),
|
||||||
|
);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1349,21 +1406,22 @@ fn get_lit_str<'a>(
|
|||||||
if let syn::Lit::Str(ref lit) = *lit {
|
if let syn::Lit::Str(ref lit) = *lit {
|
||||||
Ok(lit)
|
Ok(lit)
|
||||||
} else {
|
} else {
|
||||||
cx.error_spanned_by(lit, format!(
|
cx.error_spanned_by(
|
||||||
|
lit,
|
||||||
|
format!(
|
||||||
"expected serde {} attribute to be a string: `{} = \"...\"`",
|
"expected serde {} attribute to be a string: `{} = \"...\"`",
|
||||||
attr_name, meta_item_name
|
attr_name, meta_item_name
|
||||||
));
|
),
|
||||||
|
);
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_lit_into_path(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn::Path, ()> {
|
fn parse_lit_into_path(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn::Path, ()> {
|
||||||
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
|
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
|
||||||
parse_lit_str(string)
|
parse_lit_str(string).map_err(|_| {
|
||||||
.map_err(|_| cx.error_spanned_by(
|
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
|
||||||
lit,
|
})
|
||||||
format!("failed to parse path: {:?}", string.value()),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_lit_into_expr_path(
|
fn parse_lit_into_expr_path(
|
||||||
@@ -1372,11 +1430,9 @@ fn parse_lit_into_expr_path(
|
|||||||
lit: &syn::Lit,
|
lit: &syn::Lit,
|
||||||
) -> Result<syn::ExprPath, ()> {
|
) -> Result<syn::ExprPath, ()> {
|
||||||
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
|
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
|
||||||
parse_lit_str(string)
|
parse_lit_str(string).map_err(|_| {
|
||||||
.map_err(|_| cx.error_spanned_by(
|
cx.error_spanned_by(lit, format!("failed to parse path: {:?}", string.value()))
|
||||||
lit,
|
})
|
||||||
format!("failed to parse path: {:?}", string.value()),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_lit_into_where(
|
fn parse_lit_into_where(
|
||||||
@@ -1401,11 +1457,10 @@ fn parse_lit_into_ty(cx: &Ctxt, attr_name: &Ident, lit: &syn::Lit) -> Result<syn
|
|||||||
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
|
let string = try!(get_lit_str(cx, attr_name, attr_name, lit));
|
||||||
|
|
||||||
parse_lit_str(string).map_err(|_| {
|
parse_lit_str(string).map_err(|_| {
|
||||||
cx.error_spanned_by(lit, format!(
|
cx.error_spanned_by(
|
||||||
"failed to parse type: {} = {:?}",
|
lit,
|
||||||
attr_name,
|
format!("failed to parse type: {} = {:?}", attr_name, string.value()),
|
||||||
string.value()
|
)
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1434,19 +1489,16 @@ fn parse_lit_into_lifetimes(
|
|||||||
let mut set = BTreeSet::new();
|
let mut set = BTreeSet::new();
|
||||||
for lifetime in lifetimes {
|
for lifetime in lifetimes {
|
||||||
if !set.insert(lifetime.clone()) {
|
if !set.insert(lifetime.clone()) {
|
||||||
cx.error_spanned_by(
|
cx.error_spanned_by(lit, format!("duplicate borrowed lifetime `{}`", lifetime));
|
||||||
lit,
|
|
||||||
format!("duplicate borrowed lifetime `{}`", lifetime),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(set);
|
return Ok(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.error_spanned_by(lit, format!(
|
cx.error_spanned_by(
|
||||||
"failed to parse borrowed lifetimes: {:?}",
|
lit,
|
||||||
string.value()
|
format!("failed to parse borrowed lifetimes: {:?}", string.value()),
|
||||||
));
|
);
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,52 +198,67 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
|||||||
for variant in variants.iter() {
|
for variant in variants.iter() {
|
||||||
if variant.attrs.serialize_with().is_some() {
|
if variant.attrs.serialize_with().is_some() {
|
||||||
if variant.attrs.skip_serializing() {
|
if variant.attrs.skip_serializing() {
|
||||||
cx.error_spanned_by(variant.original, format!(
|
cx.error_spanned_by(
|
||||||
|
variant.original,
|
||||||
|
format!(
|
||||||
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||||
#[serde(skip_serializing)]",
|
#[serde(skip_serializing)]",
|
||||||
variant.ident
|
variant.ident
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
let member = member_message(&field.member);
|
let member = member_message(&field.member);
|
||||||
|
|
||||||
if field.attrs.skip_serializing() {
|
if field.attrs.skip_serializing() {
|
||||||
cx.error_spanned_by(variant.original, format!(
|
cx.error_spanned_by(
|
||||||
|
variant.original,
|
||||||
|
format!(
|
||||||
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||||
a field {} marked with #[serde(skip_serializing)]",
|
a field {} marked with #[serde(skip_serializing)]",
|
||||||
variant.ident, member
|
variant.ident, member
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.attrs.skip_serializing_if().is_some() {
|
if field.attrs.skip_serializing_if().is_some() {
|
||||||
cx.error_spanned_by(variant.original, format!(
|
cx.error_spanned_by(
|
||||||
|
variant.original,
|
||||||
|
format!(
|
||||||
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||||
a field {} marked with #[serde(skip_serializing_if)]",
|
a field {} marked with #[serde(skip_serializing_if)]",
|
||||||
variant.ident, member
|
variant.ident, member
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if variant.attrs.deserialize_with().is_some() {
|
if variant.attrs.deserialize_with().is_some() {
|
||||||
if variant.attrs.skip_deserializing() {
|
if variant.attrs.skip_deserializing() {
|
||||||
cx.error_spanned_by(variant.original, format!(
|
cx.error_spanned_by(
|
||||||
|
variant.original,
|
||||||
|
format!(
|
||||||
"variant `{}` cannot have both #[serde(deserialize_with)] and \
|
"variant `{}` cannot have both #[serde(deserialize_with)] and \
|
||||||
#[serde(skip_deserializing)]",
|
#[serde(skip_deserializing)]",
|
||||||
variant.ident
|
variant.ident
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for field in &variant.fields {
|
for field in &variant.fields {
|
||||||
if field.attrs.skip_deserializing() {
|
if field.attrs.skip_deserializing() {
|
||||||
let member = member_message(&field.member);
|
let member = member_message(&field.member);
|
||||||
|
|
||||||
cx.error_spanned_by(variant.original, format!(
|
cx.error_spanned_by(
|
||||||
|
variant.original,
|
||||||
|
format!(
|
||||||
"variant `{}` cannot have both #[serde(deserialize_with)] \
|
"variant `{}` cannot have both #[serde(deserialize_with)] \
|
||||||
and a field {} marked with #[serde(skip_deserializing)]",
|
and a field {} marked with #[serde(skip_deserializing)]",
|
||||||
variant.ident, member
|
variant.ident, member
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,10 +280,12 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
|
EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let diagnose_conflict = || cx.error_spanned_by(
|
let diagnose_conflict = || {
|
||||||
|
cx.error_spanned_by(
|
||||||
cont.original,
|
cont.original,
|
||||||
format!("variant field name `{}` conflicts with internal tag", tag),
|
format!("variant field name `{}` conflicts with internal tag", tag),
|
||||||
);
|
)
|
||||||
|
};
|
||||||
|
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
match variant.style {
|
match variant.style {
|
||||||
@@ -303,10 +320,13 @@ fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if type_tag == content_tag {
|
if type_tag == content_tag {
|
||||||
cx.error_spanned_by(cont.original, format!(
|
cx.error_spanned_by(
|
||||||
|
cont.original,
|
||||||
|
format!(
|
||||||
"enum tags `{}` for type and content conflict with each other",
|
"enum tags `{}` for type and content conflict with each other",
|
||||||
type_tag
|
type_tag
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.81")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.82")]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
|||||||
None => {
|
None => {
|
||||||
let span = transparent_field.original.span();
|
let span = transparent_field.original.span();
|
||||||
quote_spanned!(span=> _serde::Serialize::serialize)
|
quote_spanned!(span=> _serde::Serialize::serialize)
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ path = "lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "0.4"
|
proc-macro2 = "0.4"
|
||||||
syn = { version = "0.15", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
quote = "0.6.3"
|
||||||
|
syn = { version = "0.15", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "serde-rs/serde" }
|
travis-ci = { repository = "serde-rs/serde" }
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
extern crate proc_macro2;
|
extern crate proc_macro2;
|
||||||
|
extern crate quote;
|
||||||
|
|
||||||
#[path = "src/mod.rs"]
|
#[path = "src/mod.rs"]
|
||||||
mod internals;
|
mod internals;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.81" # remember to update html_root_url
|
version = "1.0.82" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||||
|
|||||||
@@ -153,7 +153,7 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.81")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.82")]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
|
|||||||
@@ -93,6 +93,15 @@ where
|
|||||||
a5: E,
|
a5: E,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct DefaultTupleStruct<A, B, C>(
|
||||||
|
A,
|
||||||
|
#[serde(default)] B,
|
||||||
|
#[serde(default = "MyDefault::my_default")] C,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
C: MyDefault;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
struct CollectOther {
|
struct CollectOther {
|
||||||
a: u32,
|
a: u32,
|
||||||
@@ -186,8 +195,37 @@ fn test_default_struct() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_default_tuple() {
|
||||||
|
assert_de_tokens(
|
||||||
|
&DefaultTupleStruct(1, 2, 3),
|
||||||
|
&[
|
||||||
|
Token::TupleStruct {
|
||||||
|
name: "DefaultTupleStruct",
|
||||||
|
len: 3,
|
||||||
|
},
|
||||||
|
Token::I32(1),
|
||||||
|
Token::I32(2),
|
||||||
|
Token::I32(3),
|
||||||
|
Token::TupleStructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&DefaultTupleStruct(1, 0, 123),
|
||||||
|
&[
|
||||||
|
Token::TupleStruct {
|
||||||
|
name: "DefaultTupleStruct",
|
||||||
|
len: 3,
|
||||||
|
},
|
||||||
|
Token::I32(1),
|
||||||
|
Token::TupleStructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
enum DefaultEnum<A, B, C, D, E>
|
enum DefaultStructVariant<A, B, C, D, E>
|
||||||
where
|
where
|
||||||
C: MyDefault,
|
C: MyDefault,
|
||||||
E: MyDefault,
|
E: MyDefault,
|
||||||
@@ -205,10 +243,22 @@ where
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
enum DefaultTupleVariant<A, B, C>
|
||||||
|
where
|
||||||
|
C: MyDefault,
|
||||||
|
{
|
||||||
|
Tuple(
|
||||||
|
A,
|
||||||
|
#[serde(default)] B,
|
||||||
|
#[serde(default = "MyDefault::my_default")] C,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_enum() {
|
fn test_default_struct_variant() {
|
||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&DefaultEnum::Struct {
|
&DefaultStructVariant::Struct {
|
||||||
a1: 1,
|
a1: 1,
|
||||||
a2: 2,
|
a2: 2,
|
||||||
a3: 3,
|
a3: 3,
|
||||||
@@ -217,7 +267,7 @@ fn test_default_enum() {
|
|||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
Token::StructVariant {
|
Token::StructVariant {
|
||||||
name: "DefaultEnum",
|
name: "DefaultStructVariant",
|
||||||
variant: "Struct",
|
variant: "Struct",
|
||||||
len: 3,
|
len: 3,
|
||||||
},
|
},
|
||||||
@@ -236,7 +286,7 @@ fn test_default_enum() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&DefaultEnum::Struct {
|
&DefaultStructVariant::Struct {
|
||||||
a1: 1,
|
a1: 1,
|
||||||
a2: 0,
|
a2: 0,
|
||||||
a3: 123,
|
a3: 123,
|
||||||
@@ -245,7 +295,7 @@ fn test_default_enum() {
|
|||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
Token::StructVariant {
|
Token::StructVariant {
|
||||||
name: "DefaultEnum",
|
name: "DefaultStructVariant",
|
||||||
variant: "Struct",
|
variant: "Struct",
|
||||||
len: 3,
|
len: 3,
|
||||||
},
|
},
|
||||||
@@ -256,6 +306,37 @@ fn test_default_enum() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_default_tuple_variant() {
|
||||||
|
assert_de_tokens(
|
||||||
|
&DefaultTupleVariant::Tuple(1, 2, 3),
|
||||||
|
&[
|
||||||
|
Token::TupleVariant {
|
||||||
|
name: "DefaultTupleVariant",
|
||||||
|
variant: "Tuple",
|
||||||
|
len: 3,
|
||||||
|
},
|
||||||
|
Token::I32(1),
|
||||||
|
Token::I32(2),
|
||||||
|
Token::I32(3),
|
||||||
|
Token::TupleVariantEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&DefaultTupleVariant::Tuple(1, 0, 123),
|
||||||
|
&[
|
||||||
|
Token::TupleVariant {
|
||||||
|
name: "DefaultTupleVariant",
|
||||||
|
variant: "Tuple",
|
||||||
|
len: 3,
|
||||||
|
},
|
||||||
|
Token::I32(1),
|
||||||
|
Token::TupleVariantEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Does not implement std::default::Default.
|
// Does not implement std::default::Default.
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
struct NoStdDefault(i8);
|
struct NoStdDefault(i8);
|
||||||
|
|||||||
Reference in New Issue
Block a user