mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 21:08:00 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1799547846 | |||
| 2dbeefb11b | |||
| 8a3c29ff19 | |||
| defc24d361 | |||
| 2316610760 | |||
| c09e2bd690 | |||
| fe7dcc4cd8 | |||
| a20e66e131 | |||
| 1c1a5d95cd | |||
| ee3c2372fb | |||
| bfb020d975 | |||
| 6805bba308 | |||
| 2659b94a62 | |||
| c451415d9f | |||
| 553a9ff15f | |||
| 6f5eb7d207 | |||
| 55615e8f8e |
+3
-3
@@ -27,11 +27,11 @@ pull request with your changes. If anything does not pass, typically it will be
|
||||
easier to iterate and fix it locally than waiting for the CI servers to run
|
||||
tests for you.
|
||||
|
||||
##### In the [`serde`] directory
|
||||
##### In the [`serde_core`] directory
|
||||
|
||||
```sh
|
||||
# Test all the example code in Serde documentation
|
||||
cargo test --features derive
|
||||
cargo test
|
||||
```
|
||||
|
||||
##### In the [`test_suite`] directory
|
||||
@@ -43,7 +43,7 @@ cargo +nightly test --features unstable
|
||||
|
||||
Note that this test suite currently only supports running on a nightly compiler.
|
||||
|
||||
[`serde`]: https://github.com/serde-rs/serde/tree/master/serde
|
||||
[`serde_core`]: https://github.com/serde-rs/serde/tree/master/serde_core
|
||||
[`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite
|
||||
|
||||
## Conduct
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.225"
|
||||
version = "1.0.226"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
build = "build.rs"
|
||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||
@@ -15,7 +15,7 @@ repository = "https://github.com/serde-rs/serde"
|
||||
rust-version = "1.56"
|
||||
|
||||
[dependencies]
|
||||
serde_core = { version = "=1.0.225", path = "../serde_core", default-features = false, features = ["result"] }
|
||||
serde_core = { version = "=1.0.226", path = "../serde_core", default-features = false, features = ["result"] }
|
||||
serde_derive = { version = "1", optional = true, path = "../serde_derive" }
|
||||
|
||||
[package.metadata.playground]
|
||||
@@ -26,6 +26,7 @@ features = ["derive", "rc", "unstable"]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--generate-macro-expansion",
|
||||
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.225")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.226")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Show which crate feature enables conditionally compiled APIs in documentation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_core"
|
||||
version = "1.0.225"
|
||||
version = "1.0.226"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
build = "build.rs"
|
||||
categories = ["encoding", "no-std", "no-std::no-alloc"]
|
||||
@@ -25,6 +25,7 @@ features = ["rc", "result", "unstable"]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--generate-macro-expansion",
|
||||
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||
@@ -36,7 +37,7 @@ rustdoc-args = [
|
||||
# is compatible with exactly one serde release because the generated code
|
||||
# involves nonpublic APIs which are not bound by semver.
|
||||
[target.'cfg(any())'.dependencies]
|
||||
serde_derive = { version = "=1.0.225", path = "../serde_derive" }
|
||||
serde_derive = { version = "=1.0.226", path = "../serde_derive" }
|
||||
|
||||
|
||||
### FEATURES #################################################################
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde_core/1.0.225")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_core/1.0.226")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Show which crate feature enables conditionally compiled APIs in documentation.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.225"
|
||||
version = "1.0.226"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
categories = ["no-std", "no-std::no-alloc"]
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
@@ -34,6 +34,7 @@ serde = { version = "1", path = "../serde" }
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--generate-macro-expansion",
|
||||
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||
|
||||
+34
-27
@@ -352,6 +352,7 @@ fn deserialize_in_place_body(_cont: &Container, _params: &Parameters) -> Option<
|
||||
None
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for a type with `#[serde(transparent)]` attribute
|
||||
fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
||||
let fields = match &cont.data {
|
||||
Data::Struct(_, fields) => fields,
|
||||
@@ -394,6 +395,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for a type with `#[serde(from)]` attribute
|
||||
fn deserialize_from(type_from: &syn::Type) -> Fragment {
|
||||
quote_block! {
|
||||
_serde::#private::Result::map(
|
||||
@@ -402,6 +404,7 @@ fn deserialize_from(type_from: &syn::Type) -> Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for a type with `#[serde(try_from)]` attribute
|
||||
fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment {
|
||||
quote_block! {
|
||||
_serde::#private::Result::and_then(
|
||||
@@ -410,6 +413,7 @@ fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for a `struct Unit;`
|
||||
fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment {
|
||||
let this_type = ¶ms.this_type;
|
||||
let this_value = ¶ms.this_value;
|
||||
@@ -465,6 +469,7 @@ enum TupleForm<'a> {
|
||||
Untagged(&'a syn::Ident, TokenStream),
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for a `struct Tuple(...);` including `struct Newtype(T);`
|
||||
fn deserialize_tuple(
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
@@ -587,6 +592,7 @@ fn deserialize_tuple(
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize_in_place` body for a `struct Tuple(...);` including `struct Newtype(T);`
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_tuple_in_place(
|
||||
params: &Parameters,
|
||||
@@ -937,6 +943,7 @@ enum StructForm<'a> {
|
||||
Untagged(&'a syn::Ident, TokenStream),
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for a `struct Struct {...}`
|
||||
fn deserialize_struct(
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
@@ -1119,6 +1126,7 @@ fn deserialize_struct(
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}`
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_struct_in_place(
|
||||
params: &Parameters,
|
||||
@@ -1209,6 +1217,7 @@ fn deserialize_struct_in_place(
|
||||
})
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}`
|
||||
fn deserialize_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
@@ -1284,6 +1293,7 @@ fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) {
|
||||
(variants_stmt, variant_visitor)
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` without additional attributes
|
||||
fn deserialize_externally_tagged_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
@@ -1378,6 +1388,7 @@ fn deserialize_externally_tagged_enum(
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag)]` attribute
|
||||
fn deserialize_internally_tagged_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
@@ -1425,6 +1436,7 @@ fn deserialize_internally_tagged_enum(
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag, content)]` attributes
|
||||
fn deserialize_adjacently_tagged_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
@@ -1474,21 +1486,6 @@ fn deserialize_adjacently_tagged_enum(
|
||||
quote! { _serde::#private::de::TagContentOtherFieldVisitor }
|
||||
};
|
||||
|
||||
let tag_or_content = quote! {
|
||||
#field_visitor_ty {
|
||||
tag: #tag,
|
||||
content: #content,
|
||||
}
|
||||
};
|
||||
|
||||
let variant_seed = quote! {
|
||||
_serde::#private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
|
||||
enum_name: #rust_name,
|
||||
variants: VARIANTS,
|
||||
fields_enum: _serde::#private::PhantomData
|
||||
}
|
||||
};
|
||||
|
||||
let mut missing_content = quote! {
|
||||
_serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
|
||||
};
|
||||
@@ -1533,11 +1530,18 @@ fn deserialize_adjacently_tagged_enum(
|
||||
|
||||
// Advance the map by one key, returning early in case of error.
|
||||
let next_key = quote! {
|
||||
_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)?
|
||||
_serde::de::MapAccess::next_key_seed(&mut __map, #field_visitor_ty {
|
||||
tag: #tag,
|
||||
content: #content,
|
||||
})?
|
||||
};
|
||||
|
||||
let variant_from_map = quote! {
|
||||
_serde::de::MapAccess::next_value_seed(&mut __map, #variant_seed)?
|
||||
_serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
|
||||
enum_name: #rust_name,
|
||||
variants: VARIANTS,
|
||||
fields_enum: _serde::#private::PhantomData
|
||||
})?
|
||||
};
|
||||
|
||||
// When allowing unknown fields, we want to transparently step through keys
|
||||
@@ -1589,10 +1593,13 @@ fn deserialize_adjacently_tagged_enum(
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
let __ret = match #variant_from_map {
|
||||
// Deserialize the buffered content now that we know the variant.
|
||||
#(#variant_arms)*
|
||||
}?;
|
||||
let __seed = __Seed {
|
||||
variant: #variant_from_map,
|
||||
marker: _serde::#private::PhantomData,
|
||||
lifetime: _serde::#private::PhantomData,
|
||||
};
|
||||
let __deserializer = _serde::#private::de::ContentDeserializer::<__A::Error>::new(__content);
|
||||
let __ret = _serde::de::DeserializeSeed::deserialize(__seed, __deserializer)?;
|
||||
// Visit remaining keys, looking for duplicates.
|
||||
#visit_remaining_keys
|
||||
}
|
||||
@@ -1605,7 +1612,7 @@ fn deserialize_adjacently_tagged_enum(
|
||||
|
||||
#[doc(hidden)]
|
||||
struct __Seed #de_impl_generics #where_clause {
|
||||
field: __Field,
|
||||
variant: __Field,
|
||||
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
||||
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
||||
}
|
||||
@@ -1618,7 +1625,7 @@ fn deserialize_adjacently_tagged_enum(
|
||||
where
|
||||
__D: _serde::Deserializer<#delife>,
|
||||
{
|
||||
match self.field {
|
||||
match self.variant {
|
||||
#(#variant_arms)*
|
||||
}
|
||||
}
|
||||
@@ -1658,7 +1665,7 @@ fn deserialize_adjacently_tagged_enum(
|
||||
_serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => {
|
||||
let __ret = _serde::de::MapAccess::next_value_seed(&mut __map,
|
||||
__Seed {
|
||||
field: __field,
|
||||
variant: __field,
|
||||
marker: _serde::#private::PhantomData,
|
||||
lifetime: _serde::#private::PhantomData,
|
||||
})?;
|
||||
@@ -1677,7 +1684,6 @@ fn deserialize_adjacently_tagged_enum(
|
||||
match #next_relevant_key {
|
||||
// Second key is the tag.
|
||||
_serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => {
|
||||
let __deserializer = _serde::#private::de::ContentDeserializer::<__A::Error>::new(__content);
|
||||
#finish_content_then_tag
|
||||
}
|
||||
// Second key is a duplicate of the content.
|
||||
@@ -1703,12 +1709,12 @@ fn deserialize_adjacently_tagged_enum(
|
||||
{
|
||||
// Visit the first element - the tag.
|
||||
match _serde::de::SeqAccess::next_element(&mut __seq)? {
|
||||
_serde::#private::Some(__field) => {
|
||||
_serde::#private::Some(__variant) => {
|
||||
// Visit the second element - the content.
|
||||
match _serde::de::SeqAccess::next_element_seed(
|
||||
&mut __seq,
|
||||
__Seed {
|
||||
field: __field,
|
||||
variant: __variant,
|
||||
marker: _serde::#private::PhantomData,
|
||||
lifetime: _serde::#private::PhantomData,
|
||||
},
|
||||
@@ -1742,6 +1748,7 @@ fn deserialize_adjacently_tagged_enum(
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(untagged)]` attribute
|
||||
fn deserialize_untagged_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.225")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.226")]
|
||||
#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
|
||||
@@ -24,6 +24,7 @@ syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "print
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
rustdoc-args = [
|
||||
"--generate-link-to-definition",
|
||||
"--generate-macro-expansion",
|
||||
"--extern-html-root-url=core=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=alloc=https://doc.rust-lang.org",
|
||||
"--extern-html-root-url=std=https://doc.rust-lang.org",
|
||||
|
||||
@@ -2697,23 +2697,42 @@ mod flatten {
|
||||
|
||||
#[test]
|
||||
fn newtype() {
|
||||
let value = Flatten {
|
||||
data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])),
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
};
|
||||
assert_tokens(
|
||||
&Flatten {
|
||||
data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])),
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
},
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// data
|
||||
Token::Str("Newtype"), // variant
|
||||
Token::Map { len: Some(1) },
|
||||
Token::Str("key"),
|
||||
Token::Str("value"),
|
||||
Token::MapEnd,
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
// data
|
||||
Token::Str("Newtype"), // variant
|
||||
Token::Map { len: Some(1) },
|
||||
Token::Str("key"),
|
||||
Token::Str("value"),
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
|
||||
@@ -2721,23 +2740,42 @@ mod flatten {
|
||||
// via FlatMapDeserializer::deserialize_enum
|
||||
#[test]
|
||||
fn tuple() {
|
||||
let value = Flatten {
|
||||
data: Enum::Tuple(0, 42),
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
};
|
||||
assert_tokens(
|
||||
&Flatten {
|
||||
data: Enum::Tuple(0, 42),
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
},
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// data
|
||||
Token::Str("Tuple"), // variant
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U32(0),
|
||||
Token::U32(42),
|
||||
Token::SeqEnd,
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
// data
|
||||
Token::Str("Tuple"), // variant
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U32(0),
|
||||
Token::U32(42),
|
||||
Token::SeqEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
|
||||
@@ -2745,26 +2783,45 @@ mod flatten {
|
||||
// via FlatMapDeserializer::deserialize_enum
|
||||
#[test]
|
||||
fn struct_from_seq() {
|
||||
assert_de_tokens(
|
||||
&Flatten {
|
||||
data: Enum::Struct {
|
||||
index: 0,
|
||||
value: 42,
|
||||
},
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
let value = Flatten {
|
||||
data: Enum::Struct {
|
||||
index: 0,
|
||||
value: 42,
|
||||
},
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
};
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// data
|
||||
Token::Str("Struct"), // variant
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U32(0), // index
|
||||
Token::U32(42), // value
|
||||
Token::SeqEnd,
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
// data
|
||||
Token::Str("Struct"), // variant
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U32(0), // index
|
||||
Token::U32(42), // value
|
||||
Token::SeqEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
|
||||
@@ -2772,16 +2829,18 @@ mod flatten {
|
||||
// via FlatMapDeserializer::deserialize_enum
|
||||
#[test]
|
||||
fn struct_from_map() {
|
||||
assert_tokens(
|
||||
&Flatten {
|
||||
data: Enum::Struct {
|
||||
index: 0,
|
||||
value: 42,
|
||||
},
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
let value = Flatten {
|
||||
data: Enum::Struct {
|
||||
index: 0,
|
||||
value: 42,
|
||||
},
|
||||
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
|
||||
};
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// data
|
||||
Token::Str("Struct"), // variant
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
@@ -2792,11 +2851,33 @@ mod flatten {
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// extra
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
// data
|
||||
Token::Str("Struct"), // variant
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "Struct",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2817,6 +2898,7 @@ mod flatten {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "tag", content = "content")]
|
||||
enum Enum {
|
||||
Unit,
|
||||
Newtype(NewtypeVariant),
|
||||
Struct { index: u32, value: u32 },
|
||||
}
|
||||
@@ -2827,24 +2909,357 @@ mod flatten {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn struct_() {
|
||||
fn unit() {
|
||||
let value = Flatten {
|
||||
outer: 42,
|
||||
data: NewtypeWrapper(Enum::Unit),
|
||||
};
|
||||
// Field order: outer, [tag]
|
||||
assert_tokens(
|
||||
&Flatten {
|
||||
outer: 42,
|
||||
data: NewtypeWrapper(Enum::Struct {
|
||||
index: 0,
|
||||
value: 42,
|
||||
}),
|
||||
},
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
// content missing
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
// content missing
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: outer, [tag, content]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Unit,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: outer, [content, tag]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Unit,
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag, content], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Unit,
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [content, tag], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Unit,
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag], outer, [content]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Unit,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [content], outer, [tag]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Unit,
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Unit",
|
||||
},
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype() {
|
||||
let value = Flatten {
|
||||
outer: 42,
|
||||
data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })),
|
||||
};
|
||||
// Field order: outer, [tag, content]
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
},
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: outer, [content, tag]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag, content], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
},
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [content, tag], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
},
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag], outer, [content]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
},
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [content], outer, [tag]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
},
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn struct_() {
|
||||
let value = Flatten {
|
||||
outer: 42,
|
||||
data: NewtypeWrapper(Enum::Struct {
|
||||
index: 0,
|
||||
value: 42,
|
||||
}),
|
||||
};
|
||||
// Field order: outer, [tag, content]
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Struct",
|
||||
},
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
@@ -2858,32 +3273,143 @@ mod flatten {
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newtype() {
|
||||
assert_tokens(
|
||||
&Flatten {
|
||||
outer: 42,
|
||||
data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })),
|
||||
},
|
||||
// Field order: outer, [content, tag]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "Struct",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Newtype",
|
||||
variant: "Struct",
|
||||
},
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag, content], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Struct",
|
||||
},
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "NewtypeVariant",
|
||||
len: 2,
|
||||
name: "Struct",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [content, tag], outer
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "Struct",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Struct",
|
||||
},
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [tag], outer, [content]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Struct",
|
||||
},
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "Struct",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
// Field order: [content], outer, [tag]
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// content
|
||||
Token::Str("content"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "Struct",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
// outer
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
// tag
|
||||
Token::Str("tag"),
|
||||
Token::UnitVariant {
|
||||
name: "Enum",
|
||||
variant: "Struct",
|
||||
},
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
@@ -2917,17 +3443,20 @@ mod flatten {
|
||||
D { d: i32 },
|
||||
}
|
||||
|
||||
let value = Flatten {
|
||||
x: X::B { b: 1 },
|
||||
y: Y::D { d: 2 },
|
||||
};
|
||||
assert_tokens(
|
||||
&Flatten {
|
||||
x: X::B { b: 1 },
|
||||
y: Y::D { d: 2 },
|
||||
},
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// x
|
||||
Token::Str("typeX"),
|
||||
Token::Str("B"),
|
||||
Token::Str("b"),
|
||||
Token::I32(1),
|
||||
// y
|
||||
Token::Str("typeY"),
|
||||
Token::Str("D"),
|
||||
Token::Str("d"),
|
||||
@@ -2935,11 +3464,28 @@ mod flatten {
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// y
|
||||
Token::Str("typeY"),
|
||||
Token::Str("D"),
|
||||
Token::Str("d"),
|
||||
Token::I32(2),
|
||||
// x
|
||||
Token::Str("typeX"),
|
||||
Token::Str("B"),
|
||||
Token::Str("b"),
|
||||
Token::I32(1),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit_enum_with_unknown_fields() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Flatten {
|
||||
#[serde(flatten)]
|
||||
x: X,
|
||||
@@ -2947,31 +3493,49 @@ mod flatten {
|
||||
y: Y,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "typeX")]
|
||||
enum X {
|
||||
A,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "typeY")]
|
||||
enum Y {
|
||||
B { c: u32 },
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&Flatten {
|
||||
x: X::A,
|
||||
y: Y::B { c: 0 },
|
||||
},
|
||||
let value = Flatten {
|
||||
x: X::A,
|
||||
y: Y::B { c: 0 },
|
||||
};
|
||||
assert_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// x
|
||||
Token::Str("typeX"),
|
||||
Token::Str("A"),
|
||||
// y
|
||||
Token::Str("typeY"),
|
||||
Token::Str("B"),
|
||||
Token::Str("c"),
|
||||
Token::I32(0),
|
||||
Token::U32(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_de_tokens(
|
||||
&value,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
// y
|
||||
Token::Str("typeY"),
|
||||
Token::Str("B"),
|
||||
Token::Str("c"),
|
||||
Token::U32(0),
|
||||
// x
|
||||
Token::Str("typeX"),
|
||||
Token::Str("A"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user