mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-27 18:07:57 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 05a5b7e3c6 | |||
| 3bff326fb3 | |||
| aaadd93878 | |||
| 9c864f0b02 | |||
| 070cce0d9c | |||
| b58e8bac12 | |||
| ada50b077e | |||
| 5e313a7330 | |||
| 2a36d11238 | |||
| b6685cf9dd | |||
| fc273c6763 | |||
| bd7b0e257e | |||
| 73931692b2 | |||
| 4d93e9f44c | |||
| da55ed7e8d | |||
| e3617e1f28 | |||
| 431636af0d | |||
| 891ced598a | |||
| 5c33931422 | |||
| f709fc05b0 | |||
| 089aae1292 | |||
| 855acaf112 | |||
| 7ca7720262 | |||
| 78fea3aa4a | |||
| 1efb8b6a53 | |||
| bc1960b106 | |||
| 967023b755 | |||
| bb51e68f16 |
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.181"
|
version = "1.0.183"
|
||||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.181"
|
version = "1.0.183"
|
||||||
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
authors = ["David Tolnay <dtolnay@gmail.com>"]
|
||||||
categories = ["no-std", "no-std::no-alloc"]
|
categories = ["no-std", "no-std::no-alloc"]
|
||||||
description = "Implementation of #[derive(Serialize, Deserialize)]"
|
description = "Implementation of #[derive(Serialize, Deserialize)]"
|
||||||
|
|||||||
@@ -13,7 +13,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.181")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.183")]
|
||||||
|
|
||||||
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
|
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
|
||||||
include!("lib_from_source.rs");
|
include!("lib_from_source.rs");
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.181" # remember to update html_root_url and serde_derive dependency
|
version = "1.0.183" # remember to update html_root_url and serde_derive dependency
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||||
@@ -15,7 +15,7 @@ repository = "https://github.com/serde-rs/serde"
|
|||||||
rust-version = "1.31"
|
rust-version = "1.31"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_derive = { version = "=1.0.181", optional = true, path = "../serde_derive" }
|
serde_derive = { version = "=1.0.183", optional = true, path = "../serde_derive" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_derive = { version = "1", path = "../serde_derive" }
|
serde_derive = { version = "1", path = "../serde_derive" }
|
||||||
|
|||||||
@@ -1789,6 +1789,9 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
|
|||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
|
forwarded_impl!((), Box<OsStr>, OsString::into_boxed_os_str);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
||||||
where
|
where
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,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.181")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.183")]
|
||||||
// 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.181" # remember to update html_root_url
|
version = "1.0.183" # 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>"]
|
||||||
categories = ["no-std", "no-std::no-alloc"]
|
categories = ["no-std", "no-std::no-alloc"]
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
|
|||||||
+116
-110
@@ -723,19 +723,11 @@ fn deserialize_seq(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let value_if_none = match field.attrs.default() {
|
let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting);
|
||||||
attr::Default::Default => quote!(_serde::__private::Default::default()),
|
|
||||||
attr::Default::Path(path) => quote!(#path()),
|
|
||||||
attr::Default::None => quote!(
|
|
||||||
return _serde::__private::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::__private::Some(__value) => __value,
|
_serde::__private::Some(__value) => __value,
|
||||||
_serde::__private::None => {
|
_serde::__private::None => #value_if_none,
|
||||||
#value_if_none
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
index_in_seq += 1;
|
index_in_seq += 1;
|
||||||
@@ -811,24 +803,14 @@ fn deserialize_seq_in_place(
|
|||||||
self.place.#member = #default;
|
self.place.#member = #default;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let value_if_none = match field.attrs.default() {
|
let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting);
|
||||||
attr::Default::Default => quote!(
|
|
||||||
self.place.#member = _serde::__private::Default::default();
|
|
||||||
),
|
|
||||||
attr::Default::Path(path) => quote!(
|
|
||||||
self.place.#member = #path();
|
|
||||||
),
|
|
||||||
attr::Default::None => quote!(
|
|
||||||
return _serde::__private::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 => {
|
||||||
quote! {
|
quote! {
|
||||||
if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq,
|
if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq,
|
||||||
_serde::__private::de::InPlaceSeed(&mut self.place.#member))?
|
_serde::__private::de::InPlaceSeed(&mut self.place.#member))?
|
||||||
{
|
{
|
||||||
#value_if_none
|
#value_if_none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -841,7 +823,7 @@ fn deserialize_seq_in_place(
|
|||||||
self.place.#member = __wrap.value;
|
self.place.#member = __wrap.value;
|
||||||
}
|
}
|
||||||
_serde::__private::None => {
|
_serde::__private::None => {
|
||||||
#value_if_none
|
#value_if_none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -983,12 +965,7 @@ fn deserialize_struct(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let field_visitor = Stmts(deserialize_generated_identifier(
|
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
|
||||||
&field_names_idents,
|
|
||||||
cattrs,
|
|
||||||
false,
|
|
||||||
None,
|
|
||||||
));
|
|
||||||
|
|
||||||
// untagged struct variants do not get a visit_seq method. The same applies to
|
// untagged struct variants do not get a visit_seq method. The same applies to
|
||||||
// structs that only have a map representation.
|
// structs that only have a map representation.
|
||||||
@@ -1040,7 +1017,7 @@ fn deserialize_struct(
|
|||||||
} else {
|
} else {
|
||||||
let field_names = field_names_idents
|
let field_names = field_names_idents
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(_, _, aliases)| aliases);
|
.flat_map(|&(_, _, aliases)| aliases);
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -1146,12 +1123,7 @@ fn deserialize_struct_in_place(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let field_visitor = Stmts(deserialize_generated_identifier(
|
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
|
||||||
&field_names_idents,
|
|
||||||
cattrs,
|
|
||||||
false,
|
|
||||||
None,
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut_seq = if field_names_idents.is_empty() {
|
let mut_seq = if field_names_idents.is_empty() {
|
||||||
quote!(_)
|
quote!(_)
|
||||||
@@ -1162,7 +1134,7 @@ fn deserialize_struct_in_place(
|
|||||||
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
|
let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
|
||||||
let field_names = field_names_idents
|
let field_names = field_names_idents
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(_, _, aliases)| aliases);
|
.flat_map(|&(_, _, aliases)| aliases);
|
||||||
let type_name = cattrs.name().deserialize_name();
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
|
||||||
let in_place_impl_generics = de_impl_generics.in_place();
|
let in_place_impl_generics = de_impl_generics.in_place();
|
||||||
@@ -1265,7 +1237,12 @@ fn prepare_enum_variant_enum(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other());
|
let fallthrough = deserialized_variants
|
||||||
|
.position(|(_, variant)| variant.attrs.other())
|
||||||
|
.map(|other_idx| {
|
||||||
|
let ignore_variant = variant_names_idents[other_idx].1.clone();
|
||||||
|
quote!(_serde::__private::Ok(__Field::#ignore_variant))
|
||||||
|
});
|
||||||
|
|
||||||
let variants_stmt = {
|
let variants_stmt = {
|
||||||
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
|
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
|
||||||
@@ -1279,7 +1256,8 @@ fn prepare_enum_variant_enum(
|
|||||||
&variant_names_idents,
|
&variant_names_idents,
|
||||||
cattrs,
|
cattrs,
|
||||||
true,
|
true,
|
||||||
other_idx,
|
None,
|
||||||
|
fallthrough,
|
||||||
));
|
));
|
||||||
|
|
||||||
(variants_stmt, variant_visitor)
|
(variants_stmt, variant_visitor)
|
||||||
@@ -2001,30 +1979,15 @@ fn deserialize_untagged_newtype_variant(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_generated_identifier(
|
fn deserialize_generated_identifier(
|
||||||
fields: &[(String, Ident, Vec<String>)],
|
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
is_variant: bool,
|
is_variant: bool,
|
||||||
other_idx: Option<usize>,
|
ignore_variant: Option<TokenStream>,
|
||||||
|
fallthrough: Option<TokenStream>,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let this_value = quote!(__Field);
|
let this_value = quote!(__Field);
|
||||||
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
|
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
|
||||||
|
|
||||||
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
|
|
||||||
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
|
|
||||||
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
|
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
|
||||||
} else if let Some(other_idx) = other_idx {
|
|
||||||
let ignore_variant = fields[other_idx].1.clone();
|
|
||||||
let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant));
|
|
||||||
(None, Some(fallthrough))
|
|
||||||
} else if is_variant || cattrs.deny_unknown_fields() {
|
|
||||||
(None, None)
|
|
||||||
} else {
|
|
||||||
let ignore_variant = quote!(__ignore,);
|
|
||||||
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
|
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
|
||||||
};
|
|
||||||
|
|
||||||
let visitor_impl = Stmts(deserialize_identifier(
|
let visitor_impl = Stmts(deserialize_identifier(
|
||||||
&this_value,
|
&this_value,
|
||||||
fields,
|
fields,
|
||||||
@@ -2070,6 +2033,33 @@ fn deserialize_generated_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates enum and its `Deserialize` implementation that represents each
|
||||||
|
/// non-skipped field of the struct
|
||||||
|
fn deserialize_field_identifier(
|
||||||
|
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
) -> Stmts {
|
||||||
|
let (ignore_variant, fallthrough) = if cattrs.has_flatten() {
|
||||||
|
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
|
||||||
|
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
|
||||||
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
} else if cattrs.deny_unknown_fields() {
|
||||||
|
(None, None)
|
||||||
|
} else {
|
||||||
|
let ignore_variant = quote!(__ignore,);
|
||||||
|
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
|
||||||
|
(Some(ignore_variant), Some(fallthrough))
|
||||||
|
};
|
||||||
|
|
||||||
|
Stmts(deserialize_generated_identifier(
|
||||||
|
fields,
|
||||||
|
cattrs,
|
||||||
|
false,
|
||||||
|
ignore_variant,
|
||||||
|
fallthrough,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
// Generates `Deserialize::deserialize` body for an enum with
|
// Generates `Deserialize::deserialize` body for an enum with
|
||||||
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
||||||
fn deserialize_custom_identifier(
|
fn deserialize_custom_identifier(
|
||||||
@@ -2131,7 +2121,7 @@ fn deserialize_custom_identifier(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let names = names_idents.iter().map(|(name, _, _)| name);
|
let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases);
|
||||||
|
|
||||||
let names_const = if fallthrough.is_some() {
|
let names_const = if fallthrough.is_some() {
|
||||||
None
|
None
|
||||||
@@ -2187,32 +2177,24 @@ fn deserialize_custom_identifier(
|
|||||||
|
|
||||||
fn deserialize_identifier(
|
fn deserialize_identifier(
|
||||||
this_value: &TokenStream,
|
this_value: &TokenStream,
|
||||||
fields: &[(String, Ident, Vec<String>)],
|
fields: &[(&str, Ident, &BTreeSet<String>)],
|
||||||
is_variant: bool,
|
is_variant: bool,
|
||||||
fallthrough: Option<TokenStream>,
|
fallthrough: Option<TokenStream>,
|
||||||
fallthrough_borrowed: Option<TokenStream>,
|
fallthrough_borrowed: Option<TokenStream>,
|
||||||
collect_other_fields: bool,
|
collect_other_fields: bool,
|
||||||
expecting: Option<&str>,
|
expecting: Option<&str>,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let mut flat_fields = Vec::new();
|
let str_mapping = fields.iter().map(|(_, ident, aliases)| {
|
||||||
for (_, ident, aliases) in fields {
|
// `aliases` also contains a main name
|
||||||
flat_fields.extend(aliases.iter().map(|alias| (alias, ident)));
|
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
|
||||||
}
|
});
|
||||||
|
let bytes_mapping = fields.iter().map(|(_, ident, aliases)| {
|
||||||
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
|
// `aliases` also contains a main name
|
||||||
let field_bytes: &Vec<_> = &flat_fields
|
let aliases = aliases
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, _)| Literal::byte_string(name.as_bytes()))
|
.map(|alias| Literal::byte_string(alias.as_bytes()));
|
||||||
.collect();
|
quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
|
||||||
|
});
|
||||||
let constructors: &Vec<_> = &flat_fields
|
|
||||||
.iter()
|
|
||||||
.map(|(_, ident)| quote!(#this_value::#ident))
|
|
||||||
.collect();
|
|
||||||
let main_constructors: &Vec<_> = &fields
|
|
||||||
.iter()
|
|
||||||
.map(|(_, ident, _)| quote!(#this_value::#ident))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let expecting = expecting.unwrap_or(if is_variant {
|
let expecting = expecting.unwrap_or(if is_variant {
|
||||||
"variant identifier"
|
"variant identifier"
|
||||||
@@ -2220,8 +2202,6 @@ fn deserialize_identifier(
|
|||||||
"field identifier"
|
"field identifier"
|
||||||
});
|
});
|
||||||
|
|
||||||
let index_expecting = if is_variant { "variant" } else { "field" };
|
|
||||||
|
|
||||||
let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
|
let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@@ -2269,21 +2249,6 @@ fn deserialize_identifier(
|
|||||||
&fallthrough_arm_tokens
|
&fallthrough_arm_tokens
|
||||||
};
|
};
|
||||||
|
|
||||||
let u64_fallthrough_arm_tokens;
|
|
||||||
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
|
|
||||||
fallthrough
|
|
||||||
} else {
|
|
||||||
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
|
|
||||||
u64_fallthrough_arm_tokens = quote! {
|
|
||||||
_serde::__private::Err(_serde::de::Error::invalid_value(
|
|
||||||
_serde::de::Unexpected::Unsigned(__value),
|
|
||||||
&#fallthrough_msg,
|
|
||||||
))
|
|
||||||
};
|
|
||||||
&u64_fallthrough_arm_tokens
|
|
||||||
};
|
|
||||||
|
|
||||||
let variant_indices = 0_u64..;
|
|
||||||
let visit_other = if collect_other_fields {
|
let visit_other = if collect_other_fields {
|
||||||
quote! {
|
quote! {
|
||||||
fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E>
|
fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E>
|
||||||
@@ -2378,15 +2343,33 @@ fn deserialize_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| {
|
||||||
|
let i = i as u64;
|
||||||
|
quote!(#i => _serde::__private::Ok(#this_value::#ident))
|
||||||
|
});
|
||||||
|
|
||||||
|
let u64_fallthrough_arm_tokens;
|
||||||
|
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
|
||||||
|
fallthrough
|
||||||
|
} else {
|
||||||
|
let index_expecting = if is_variant { "variant" } else { "field" };
|
||||||
|
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
|
||||||
|
u64_fallthrough_arm_tokens = quote! {
|
||||||
|
_serde::__private::Err(_serde::de::Error::invalid_value(
|
||||||
|
_serde::de::Unexpected::Unsigned(__value),
|
||||||
|
&#fallthrough_msg,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
&u64_fallthrough_arm_tokens
|
||||||
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result<Self::Value, __E>
|
fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result<Self::Value, __E>
|
||||||
where
|
where
|
||||||
__E: _serde::de::Error,
|
__E: _serde::de::Error,
|
||||||
{
|
{
|
||||||
match __value {
|
match __value {
|
||||||
#(
|
#(#u64_mapping,)*
|
||||||
#variant_indices => _serde::__private::Ok(#main_constructors),
|
|
||||||
)*
|
|
||||||
_ => #u64_fallthrough_arm,
|
_ => #u64_fallthrough_arm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2394,6 +2377,8 @@ fn deserialize_identifier(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
|
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
|
||||||
|
let str_mapping = str_mapping.clone();
|
||||||
|
let bytes_mapping = bytes_mapping.clone();
|
||||||
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
|
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
|
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
|
||||||
@@ -2401,9 +2386,7 @@ fn deserialize_identifier(
|
|||||||
__E: _serde::de::Error,
|
__E: _serde::de::Error,
|
||||||
{
|
{
|
||||||
match __value {
|
match __value {
|
||||||
#(
|
#(#str_mapping,)*
|
||||||
#field_strs => _serde::__private::Ok(#constructors),
|
|
||||||
)*
|
|
||||||
_ => {
|
_ => {
|
||||||
#value_as_borrowed_str_content
|
#value_as_borrowed_str_content
|
||||||
#fallthrough_borrowed_arm
|
#fallthrough_borrowed_arm
|
||||||
@@ -2416,9 +2399,7 @@ fn deserialize_identifier(
|
|||||||
__E: _serde::de::Error,
|
__E: _serde::de::Error,
|
||||||
{
|
{
|
||||||
match __value {
|
match __value {
|
||||||
#(
|
#(#bytes_mapping,)*
|
||||||
#field_bytes => _serde::__private::Ok(#constructors),
|
|
||||||
)*
|
|
||||||
_ => {
|
_ => {
|
||||||
#bytes_to_str
|
#bytes_to_str
|
||||||
#value_as_borrowed_bytes_content
|
#value_as_borrowed_bytes_content
|
||||||
@@ -2443,9 +2424,7 @@ fn deserialize_identifier(
|
|||||||
__E: _serde::de::Error,
|
__E: _serde::de::Error,
|
||||||
{
|
{
|
||||||
match __value {
|
match __value {
|
||||||
#(
|
#(#str_mapping,)*
|
||||||
#field_strs => _serde::__private::Ok(#constructors),
|
|
||||||
)*
|
|
||||||
_ => {
|
_ => {
|
||||||
#value_as_str_content
|
#value_as_str_content
|
||||||
#fallthrough_arm
|
#fallthrough_arm
|
||||||
@@ -2458,9 +2437,7 @@ fn deserialize_identifier(
|
|||||||
__E: _serde::de::Error,
|
__E: _serde::de::Error,
|
||||||
{
|
{
|
||||||
match __value {
|
match __value {
|
||||||
#(
|
#(#bytes_mapping,)*
|
||||||
#field_bytes => _serde::__private::Ok(#constructors),
|
|
||||||
)*
|
|
||||||
_ => {
|
_ => {
|
||||||
#bytes_to_str
|
#bytes_to_str
|
||||||
#value_as_bytes_content
|
#value_as_bytes_content
|
||||||
@@ -2993,6 +2970,35 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expr_is_missing_seq(
|
||||||
|
assign_to: Option<TokenStream>,
|
||||||
|
index: usize,
|
||||||
|
field: &Field,
|
||||||
|
cattrs: &attr::Container,
|
||||||
|
expecting: &str,
|
||||||
|
) -> TokenStream {
|
||||||
|
match field.attrs.default() {
|
||||||
|
attr::Default::Default => {
|
||||||
|
let span = field.original.span();
|
||||||
|
return quote_spanned!(span=> #assign_to _serde::__private::Default::default());
|
||||||
|
}
|
||||||
|
attr::Default::Path(path) => {
|
||||||
|
return quote_spanned!(path.span()=> #assign_to #path());
|
||||||
|
}
|
||||||
|
attr::Default::None => { /* below */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
match *cattrs.default() {
|
||||||
|
attr::Default::Default | attr::Default::Path(_) => {
|
||||||
|
let member = &field.member;
|
||||||
|
quote!(#assign_to __default.#member)
|
||||||
|
}
|
||||||
|
attr::Default::None => quote!(
|
||||||
|
return _serde::__private::Err(_serde::de::Error::invalid_length(#index, &#expecting))
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn effective_style(variant: &Variant) -> Style {
|
fn effective_style(variant: &Variant) -> Style {
|
||||||
match variant.style {
|
match variant.style {
|
||||||
Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit,
|
Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit,
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ pub struct Name {
|
|||||||
serialize_renamed: bool,
|
serialize_renamed: bool,
|
||||||
deserialize: String,
|
deserialize: String,
|
||||||
deserialize_renamed: bool,
|
deserialize_renamed: bool,
|
||||||
deserialize_aliases: Vec<String>,
|
deserialize_aliases: BTreeSet<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unraw(ident: &Ident) -> String {
|
fn unraw(ident: &Ident) -> String {
|
||||||
@@ -148,16 +148,12 @@ impl Name {
|
|||||||
de_name: Attr<String>,
|
de_name: Attr<String>,
|
||||||
de_aliases: Option<VecAttr<String>>,
|
de_aliases: Option<VecAttr<String>>,
|
||||||
) -> Name {
|
) -> Name {
|
||||||
let deserialize_aliases = match de_aliases {
|
let mut alias_set = BTreeSet::new();
|
||||||
Some(de_aliases) => {
|
if let Some(de_aliases) = de_aliases {
|
||||||
let mut alias_list = BTreeSet::new();
|
for alias_name in de_aliases.get() {
|
||||||
for alias_name in de_aliases.get() {
|
alias_set.insert(alias_name);
|
||||||
alias_list.insert(alias_name);
|
|
||||||
}
|
|
||||||
alias_list.into_iter().collect()
|
|
||||||
}
|
}
|
||||||
None => Vec::new(),
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let ser_name = ser_name.get();
|
let ser_name = ser_name.get();
|
||||||
let ser_renamed = ser_name.is_some();
|
let ser_renamed = ser_name.is_some();
|
||||||
@@ -168,27 +164,22 @@ impl Name {
|
|||||||
serialize_renamed: ser_renamed,
|
serialize_renamed: ser_renamed,
|
||||||
deserialize: de_name.unwrap_or(source_name),
|
deserialize: de_name.unwrap_or(source_name),
|
||||||
deserialize_renamed: de_renamed,
|
deserialize_renamed: de_renamed,
|
||||||
deserialize_aliases,
|
deserialize_aliases: alias_set,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the container name for the container when serializing.
|
/// Return the container name for the container when serializing.
|
||||||
pub fn serialize_name(&self) -> String {
|
pub fn serialize_name(&self) -> &str {
|
||||||
self.serialize.clone()
|
&self.serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the container name for the container when deserializing.
|
/// Return the container name for the container when deserializing.
|
||||||
pub fn deserialize_name(&self) -> String {
|
pub fn deserialize_name(&self) -> &str {
|
||||||
self.deserialize.clone()
|
&self.deserialize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_aliases(&self) -> Vec<String> {
|
fn deserialize_aliases(&self) -> &BTreeSet<String> {
|
||||||
let mut aliases = self.deserialize_aliases.clone();
|
&self.deserialize_aliases
|
||||||
let main_name = self.deserialize_name();
|
|
||||||
if !aliases.contains(&main_name) {
|
|
||||||
aliases.push(main_name);
|
|
||||||
}
|
|
||||||
aliases
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,20 +396,20 @@ impl Container {
|
|||||||
if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
|
if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
|
||||||
match &item.data {
|
match &item.data {
|
||||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||||
syn::Fields::Named(_) => {
|
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
|
||||||
default.set(&meta.path, Default::Path(path));
|
default.set(&meta.path, Default::Path(path));
|
||||||
}
|
}
|
||||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
|
syn::Fields::Unit => {
|
||||||
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
|
let msg = "#[serde(default = \"...\")] can only be used on structs that have fields";
|
||||||
cx.syn_error(meta.error(msg));
|
cx.syn_error(meta.error(msg));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
syn::Data::Enum(_) => {
|
syn::Data::Enum(_) => {
|
||||||
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
|
let msg = "#[serde(default = \"...\")] can only be used on structs";
|
||||||
cx.syn_error(meta.error(msg));
|
cx.syn_error(meta.error(msg));
|
||||||
}
|
}
|
||||||
syn::Data::Union(_) => {
|
syn::Data::Union(_) => {
|
||||||
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields";
|
let msg = "#[serde(default = \"...\")] can only be used on structs";
|
||||||
cx.syn_error(meta.error(msg));
|
cx.syn_error(meta.error(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,20 +418,20 @@ impl Container {
|
|||||||
// #[serde(default)]
|
// #[serde(default)]
|
||||||
match &item.data {
|
match &item.data {
|
||||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||||
syn::Fields::Named(_) => {
|
syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
|
||||||
default.set(meta.path, Default::Default);
|
default.set(meta.path, Default::Default);
|
||||||
}
|
}
|
||||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => {
|
syn::Fields::Unit => {
|
||||||
let msg = "#[serde(default)] can only be used on structs with named fields";
|
let msg = "#[serde(default)] can only be used on structs that have fields";
|
||||||
cx.error_spanned_by(fields, msg);
|
cx.error_spanned_by(fields, msg);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
syn::Data::Enum(_) => {
|
syn::Data::Enum(_) => {
|
||||||
let msg = "#[serde(default)] can only be used on structs with named fields";
|
let msg = "#[serde(default)] can only be used on structs";
|
||||||
cx.syn_error(meta.error(msg));
|
cx.syn_error(meta.error(msg));
|
||||||
}
|
}
|
||||||
syn::Data::Union(_) => {
|
syn::Data::Union(_) => {
|
||||||
let msg = "#[serde(default)] can only be used on structs with named fields";
|
let msg = "#[serde(default)] can only be used on structs";
|
||||||
cx.syn_error(meta.error(msg));
|
cx.syn_error(meta.error(msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -977,7 +968,7 @@ impl Variant {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aliases(&self) -> Vec<String> {
|
pub fn aliases(&self) -> &BTreeSet<String> {
|
||||||
self.name.deserialize_aliases()
|
self.name.deserialize_aliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,6 +979,9 @@ impl Variant {
|
|||||||
if !self.name.deserialize_renamed {
|
if !self.name.deserialize_renamed {
|
||||||
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
|
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
|
||||||
}
|
}
|
||||||
|
self.name
|
||||||
|
.deserialize_aliases
|
||||||
|
.insert(self.name.deserialize.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_all_rules(&self) -> RenameAllRules {
|
pub fn rename_all_rules(&self) -> RenameAllRules {
|
||||||
@@ -1316,7 +1310,7 @@ impl Field {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aliases(&self) -> Vec<String> {
|
pub fn aliases(&self) -> &BTreeSet<String> {
|
||||||
self.name.deserialize_aliases()
|
self.name.deserialize_aliases()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1327,6 +1321,9 @@ impl Field {
|
|||||||
if !self.name.deserialize_renamed {
|
if !self.name.deserialize_renamed {
|
||||||
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
|
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
|
||||||
}
|
}
|
||||||
|
self.name
|
||||||
|
.deserialize_aliases
|
||||||
|
.insert(self.name.deserialize.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_serializing(&self) -> bool {
|
pub fn skip_serializing(&self) -> bool {
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use crate::internals::ast::{Container, Data, Field, Style};
|
use crate::internals::ast::{Container, Data, Field, Style};
|
||||||
use crate::internals::attr::{Identifier, TagType};
|
use crate::internals::attr::{Default, Identifier, TagType};
|
||||||
use crate::internals::{ungroup, Ctxt, Derive};
|
use crate::internals::{ungroup, Ctxt, Derive};
|
||||||
use syn::{Member, Type};
|
use syn::{Member, Type};
|
||||||
|
|
||||||
// Cross-cutting checks that require looking at more than a single attrs object.
|
// Cross-cutting checks that require looking at more than a single attrs object.
|
||||||
// Simpler checks should happen when parsing and building the attrs.
|
// Simpler checks should happen when parsing and building the attrs.
|
||||||
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||||
|
check_default_on_tuple(cx, cont);
|
||||||
check_remote_generic(cx, cont);
|
check_remote_generic(cx, cont);
|
||||||
check_getter(cx, cont);
|
check_getter(cx, cont);
|
||||||
check_flatten(cx, cont);
|
check_flatten(cx, cont);
|
||||||
@@ -17,6 +18,39 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
|||||||
check_from_and_try_from(cx, cont);
|
check_from_and_try_from(cx, cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If some field of a tuple struct is marked #[serde(default)] then all fields
|
||||||
|
// after it must also be marked with that attribute, or the struct must have a
|
||||||
|
// container-level serde(default) attribute. A field's default value is only
|
||||||
|
// used for tuple fields if the sequence is exhausted at that point; that means
|
||||||
|
// all subsequent fields will fail to deserialize if they don't have their own
|
||||||
|
// default.
|
||||||
|
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
|
||||||
|
if let Default::None = cont.attrs.default() {
|
||||||
|
if let Data::Struct(Style::Tuple, fields) = &cont.data {
|
||||||
|
let mut first_default_index = None;
|
||||||
|
for (i, field) in fields.iter().enumerate() {
|
||||||
|
// Skipped fields automatically get the #[serde(default)]
|
||||||
|
// attribute. We are interested only on non-skipped fields here.
|
||||||
|
if field.attrs.skip_deserializing() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Default::None = field.attrs.default() {
|
||||||
|
if let Some(first) = first_default_index {
|
||||||
|
cx.error_spanned_by(
|
||||||
|
field.ty,
|
||||||
|
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if first_default_index.is_none() {
|
||||||
|
first_default_index = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remote derive definition type must have either all of the generics of the
|
// Remote derive definition type must have either all of the generics of the
|
||||||
// remote type:
|
// remote type:
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -13,7 +13,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.181")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.183")]
|
||||||
// Ignored clippy lints
|
// Ignored clippy lints
|
||||||
#![allow(
|
#![allow(
|
||||||
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
|
||||||
|
|||||||
@@ -566,7 +566,7 @@ fn serialize_externally_tagged_variant(
|
|||||||
},
|
},
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
&type_name,
|
type_name,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -631,7 +631,7 @@ fn serialize_internally_tagged_variant(
|
|||||||
StructVariant::InternallyTagged { tag, variant_name },
|
StructVariant::InternallyTagged { tag, variant_name },
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
&type_name,
|
type_name,
|
||||||
),
|
),
|
||||||
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
||||||
}
|
}
|
||||||
@@ -698,7 +698,7 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
StructVariant::Untagged,
|
StructVariant::Untagged,
|
||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
&variant_name,
|
variant_name,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -794,16 +794,16 @@ fn serialize_untagged_variant(
|
|||||||
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
|
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
|
||||||
Style::Struct => {
|
Style::Struct => {
|
||||||
let type_name = cattrs.name().serialize_name();
|
let type_name = cattrs.name().serialize_name();
|
||||||
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name)
|
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TupleVariant {
|
enum TupleVariant<'a> {
|
||||||
ExternallyTagged {
|
ExternallyTagged {
|
||||||
type_name: String,
|
type_name: &'a str,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant_name: String,
|
variant_name: &'a str,
|
||||||
},
|
},
|
||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
@@ -870,11 +870,11 @@ fn serialize_tuple_variant(
|
|||||||
enum StructVariant<'a> {
|
enum StructVariant<'a> {
|
||||||
ExternallyTagged {
|
ExternallyTagged {
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant_name: String,
|
variant_name: &'a str,
|
||||||
},
|
},
|
||||||
InternallyTagged {
|
InternallyTagged {
|
||||||
tag: &'a str,
|
tag: &'a str,
|
||||||
variant_name: String,
|
variant_name: &'a str,
|
||||||
},
|
},
|
||||||
Untagged,
|
Untagged,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#![allow(internal_features)]
|
||||||
#![feature(lang_items, start)]
|
#![feature(lang_items, start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ fn test_unknown_field_rename_struct() {
|
|||||||
Token::Str("a4"),
|
Token::Str("a4"),
|
||||||
Token::I32(3),
|
Token::I32(3),
|
||||||
],
|
],
|
||||||
"unknown field `a4`, expected one of `a1`, `a3`, `a2`, `a5`, `a6`",
|
"unknown field `a4`, expected one of `a1`, `a2`, `a3`, `a5`, `a6`",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,7 +799,7 @@ fn test_unknown_field_rename_enum() {
|
|||||||
Token::Str("d"),
|
Token::Str("d"),
|
||||||
Token::I8(2),
|
Token::I8(2),
|
||||||
],
|
],
|
||||||
"unknown field `d`, expected one of `a`, `c`, `b`, `e`, `f`",
|
"unknown field `d`, expected one of `a`, `b`, `c`, `e`, `f`",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,86 +3,186 @@
|
|||||||
#![allow(clippy::derive_partial_eq_without_eq)]
|
#![allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use serde_test::{assert_de_tokens, Token};
|
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
|
||||||
|
|
||||||
|
mod variant_identifier {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_variant_identifier() {
|
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
#[serde(variant_identifier)]
|
#[serde(variant_identifier)]
|
||||||
enum V {
|
enum V {
|
||||||
Aaa,
|
Aaa,
|
||||||
|
#[serde(alias = "Ccc", alias = "Ddd")]
|
||||||
Bbb,
|
Bbb,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
|
#[test]
|
||||||
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
|
fn variant1() {
|
||||||
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
|
assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
|
||||||
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
|
assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
|
||||||
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
|
assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
|
||||||
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
|
assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
|
||||||
|
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
|
||||||
|
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn aliases() {
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::U8(1)]);
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::U16(1)]);
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::U32(1)]);
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::U64(1)]);
|
||||||
|
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::Str("Bbb")]);
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Bbb")]);
|
||||||
|
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::Str("Ccc")]);
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ccc")]);
|
||||||
|
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::Str("Ddd")]);
|
||||||
|
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ddd")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown() {
|
||||||
|
assert_de_tokens_error::<V>(
|
||||||
|
&[Token::U8(42)],
|
||||||
|
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<V>(
|
||||||
|
&[Token::U16(42)],
|
||||||
|
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<V>(
|
||||||
|
&[Token::U32(42)],
|
||||||
|
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<V>(
|
||||||
|
&[Token::U64(42)],
|
||||||
|
"invalid value: integer `42`, expected variant index 0 <= i < 2",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<V>(
|
||||||
|
&[Token::Str("Unknown")],
|
||||||
|
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<V>(
|
||||||
|
&[Token::Bytes(b"Unknown")],
|
||||||
|
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
mod field_identifier {
|
||||||
fn test_field_identifier() {
|
use super::*;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
#[serde(field_identifier, rename_all = "snake_case")]
|
#[serde(field_identifier, rename_all = "snake_case")]
|
||||||
enum F {
|
enum F {
|
||||||
Aaa,
|
Aaa,
|
||||||
|
#[serde(alias = "ccc", alias = "ddd")]
|
||||||
Bbb,
|
Bbb,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
|
#[test]
|
||||||
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
|
fn field1() {
|
||||||
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
|
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
|
||||||
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
|
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
|
||||||
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
|
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
|
||||||
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
|
assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
|
||||||
}
|
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
|
||||||
|
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
|
||||||
#[test]
|
|
||||||
fn test_unit_fallthrough() {
|
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
|
||||||
#[serde(field_identifier, rename_all = "snake_case")]
|
|
||||||
enum F {
|
|
||||||
Aaa,
|
|
||||||
Bbb,
|
|
||||||
#[serde(other)]
|
|
||||||
Other,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens(&F::Other, &[Token::U8(42)]);
|
#[test]
|
||||||
assert_de_tokens(&F::Other, &[Token::U16(42)]);
|
fn aliases() {
|
||||||
assert_de_tokens(&F::Other, &[Token::U32(42)]);
|
assert_de_tokens(&F::Bbb, &[Token::U8(1)]);
|
||||||
assert_de_tokens(&F::Other, &[Token::U64(42)]);
|
assert_de_tokens(&F::Bbb, &[Token::U16(1)]);
|
||||||
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
assert_de_tokens(&F::Bbb, &[Token::U32(1)]);
|
||||||
}
|
assert_de_tokens(&F::Bbb, &[Token::U64(1)]);
|
||||||
|
|
||||||
#[test]
|
assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]);
|
||||||
fn test_newtype_fallthrough() {
|
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]);
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
|
||||||
#[serde(field_identifier, rename_all = "snake_case")]
|
assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]);
|
||||||
enum F {
|
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]);
|
||||||
Aaa,
|
|
||||||
Bbb,
|
assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]);
|
||||||
Other(String),
|
assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
#[test]
|
||||||
}
|
fn unknown() {
|
||||||
|
assert_de_tokens_error::<F>(
|
||||||
#[test]
|
&[Token::U8(42)],
|
||||||
fn test_newtype_fallthrough_generic() {
|
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||||
#[derive(Deserialize, Debug, PartialEq)]
|
);
|
||||||
#[serde(field_identifier, rename_all = "snake_case")]
|
assert_de_tokens_error::<F>(
|
||||||
enum F<T> {
|
&[Token::U16(42)],
|
||||||
Aaa,
|
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||||
Bbb,
|
);
|
||||||
Other(T),
|
assert_de_tokens_error::<F>(
|
||||||
|
&[Token::U32(42)],
|
||||||
|
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<F>(
|
||||||
|
&[Token::U64(42)],
|
||||||
|
"invalid value: integer `42`, expected field index 0 <= i < 2",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<F>(
|
||||||
|
&[Token::Str("unknown")],
|
||||||
|
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
|
||||||
|
);
|
||||||
|
assert_de_tokens_error::<F>(
|
||||||
|
&[Token::Bytes(b"unknown")],
|
||||||
|
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
|
#[test]
|
||||||
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
|
fn unit_fallthrough() {
|
||||||
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
|
#[serde(field_identifier, rename_all = "snake_case")]
|
||||||
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
enum F {
|
||||||
|
Aaa,
|
||||||
|
Bbb,
|
||||||
|
#[serde(other)]
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(&F::Other, &[Token::U8(42)]);
|
||||||
|
assert_de_tokens(&F::Other, &[Token::U16(42)]);
|
||||||
|
assert_de_tokens(&F::Other, &[Token::U32(42)]);
|
||||||
|
assert_de_tokens(&F::Other, &[Token::U64(42)]);
|
||||||
|
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn newtype_fallthrough() {
|
||||||
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
|
#[serde(field_identifier, rename_all = "snake_case")]
|
||||||
|
enum F {
|
||||||
|
Aaa,
|
||||||
|
Bbb,
|
||||||
|
Other(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn newtype_fallthrough_generic() {
|
||||||
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
|
#[serde(field_identifier, rename_all = "snake_case")]
|
||||||
|
enum F<T> {
|
||||||
|
Aaa,
|
||||||
|
Bbb,
|
||||||
|
Other(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
|
||||||
|
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
|
||||||
|
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
|
||||||
|
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
|
||||||
|
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
error: #[serde(default)] can only be used on structs with named fields
|
error: #[serde(default)] can only be used on structs
|
||||||
--> tests/ui/default-attribute/enum.rs:4:9
|
--> tests/ui/default-attribute/enum.rs:4:9
|
||||||
|
|
|
|
||||||
4 | #[serde(default)]
|
4 | #[serde(default)]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
error: #[serde(default = "...")] can only be used on structs with named fields
|
error: #[serde(default = "...")] can only be used on structs
|
||||||
--> tests/ui/default-attribute/enum_path.rs:4:9
|
--> tests/ui/default-attribute/enum_path.rs:4:9
|
||||||
|
|
|
|
||||||
4 | #[serde(default = "default_e")]
|
4 | #[serde(default = "default_e")]
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
use serde_derive::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(default)]
|
|
||||||
struct T(u8, u8);
|
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
error: #[serde(default)] can only be used on structs with named fields
|
|
||||||
--> tests/ui/default-attribute/nameless_struct_fields.rs:5:9
|
|
||||||
|
|
|
||||||
5 | struct T(u8, u8);
|
|
||||||
| ^^^^^^^^
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
use serde_derive::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(default = "default_t")]
|
|
||||||
struct T(u8, u8);
|
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
error: #[serde(default = "...")] can only be used on structs with named fields
|
|
||||||
--> tests/ui/default-attribute/nameless_struct_fields_path.rs:4:9
|
|
||||||
|
|
|
||||||
4 | #[serde(default = "default_t")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
use serde_derive::Deserialize;
|
||||||
|
|
||||||
|
// No errors expected.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T0(u8, u8);
|
||||||
|
|
||||||
|
// No errors expected:
|
||||||
|
// - If both fields are provided, both get value from data.
|
||||||
|
// - If only one field is provided, the second gets default value.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T1(u8, #[serde(default)] u8);
|
||||||
|
|
||||||
|
// ERROR: The first field can get default value only if sequence is empty, but
|
||||||
|
// that mean that all other fields cannot be deserialized without errors.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T2(#[serde(default)] u8, u8, u8);
|
||||||
|
|
||||||
|
// No errors expected:
|
||||||
|
// - If both fields are provided, both get value from data.
|
||||||
|
// - If only one field is provided, the second gets default value.
|
||||||
|
// - If no fields are provided, both get default value.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T3(#[serde(default)] u8, #[serde(default)] u8);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T4(u8, u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T5(#[serde(default)] u8, u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T6(u8, #[serde(default)] u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T7(#[serde(default)] u8, #[serde(default)] u8);
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
|
||||||
|
--> tests/ui/default-attribute/tuple_struct.rs:16:33
|
||||||
|
|
|
||||||
|
16 | struct T2(#[serde(default)] u8, u8, u8);
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
|
||||||
|
--> tests/ui/default-attribute/tuple_struct.rs:16:37
|
||||||
|
|
|
||||||
|
16 | struct T2(#[serde(default)] u8, u8, u8);
|
||||||
|
| ^^
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
use serde_derive::Deserialize;
|
||||||
|
|
||||||
|
fn d<T>() -> T {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No errors expected:
|
||||||
|
// - If both fields are provided, both get value from data.
|
||||||
|
// - If only one field is provided, the second gets default value.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T1(u8, #[serde(default = "d")] u8);
|
||||||
|
|
||||||
|
// ERROR: The first field can get default value only if sequence is empty, but
|
||||||
|
// that mean that all other fields cannot be deserialized without errors.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T2(#[serde(default = "d")] u8, u8, u8);
|
||||||
|
|
||||||
|
// No errors expected:
|
||||||
|
// - If both fields are provided, both get value from data.
|
||||||
|
// - If only one field is provided, the second gets default value.
|
||||||
|
// - If no fields are provided, both get default value.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct T3(#[serde(default = "d")] u8, #[serde(default = "d")] u8);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T1D(#[serde(default = "d")] u8, u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T2D(u8, #[serde(default = "d")] u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct T3D(#[serde(default = "d")] u8, #[serde(default = "d")] u8);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(default = "d")]
|
||||||
|
struct T1Path(#[serde(default)] u8, u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(default = "d")]
|
||||||
|
struct T2Path(u8, #[serde(default)] u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(default = "d")]
|
||||||
|
struct T3Path(#[serde(default)] u8, #[serde(default)] u8);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(default = "d")]
|
||||||
|
struct T1PathD(#[serde(default = "d")] u8, u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(default = "d")]
|
||||||
|
struct T2PathD(u8, #[serde(default = "d")] u8);
|
||||||
|
|
||||||
|
// No errors expected -- missing fields get default values.
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(default = "d")]
|
||||||
|
struct T3PathD(#[serde(default = "d")] u8, #[serde(default = "d")] u8);
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
|
||||||
|
--> tests/ui/default-attribute/tuple_struct_path.rs:16:39
|
||||||
|
|
|
||||||
|
16 | struct T2(#[serde(default = "d")] u8, u8, u8);
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
|
||||||
|
--> tests/ui/default-attribute/tuple_struct_path.rs:16:43
|
||||||
|
|
|
||||||
|
16 | struct T2(#[serde(default = "d")] u8, u8, u8);
|
||||||
|
| ^^
|
||||||
Reference in New Issue
Block a user