From 75e969da271da6eed0f37ef69d61844e449425ce Mon Sep 17 00:00:00 2001 From: Thomas Gauges Date: Sat, 28 Oct 2023 21:20:38 +0200 Subject: [PATCH] feat(#1587): implement serde(strict_or_some_other_name) on enums This only has an effect on struct variants. --- serde_derive/src/internals/attr.rs | 5 +- test_suite/tests/test_de_error.rs | 89 +++++++++++++++++++ .../ui/strict-or-some-other-name/enum.rs | 9 -- .../ui/strict-or-some-other-name/enum.stderr | 5 -- .../newtype-struct.stderr | 2 +- .../tuple-struct.stderr | 2 +- .../unit-struct.stderr | 2 +- 7 files changed, 96 insertions(+), 18 deletions(-) delete mode 100644 test_suite/tests/ui/strict-or-some-other-name/enum.rs delete mode 100644 test_suite/tests/ui/strict-or-some-other-name/enum.stderr diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index d29e3c5a2..05a7f60de 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -450,7 +450,7 @@ impl Container { de_bound.set_opt(&meta.path, de); } else if meta.path == STRICT_OR_SOME_OTHER_NAME { // #[serde(strict_or_some_other_name)] - let msg = "#[serde(strict_or_some_other_name)] can only be used on structs with named fields"; + let msg = "#[serde(strict_or_some_other_name)] can only be used on structs with named fields or enums"; match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => { match fields { @@ -462,6 +462,9 @@ impl Container { } }; } + syn::Data::Enum(_) => { + strict_or_some_other_name.set_true(&meta.path); + } _ => { cx.syn_error(meta.error(msg)); } diff --git a/test_suite/tests/test_de_error.rs b/test_suite/tests/test_de_error.rs index b072dfd09..dd1a8d9a7 100644 --- a/test_suite/tests/test_de_error.rs +++ b/test_suite/tests/test_de_error.rs @@ -51,6 +51,18 @@ struct StructStrictOrSomeOtherName { #[derive(Default, PartialEq, Debug)] struct NotDeserializable; +#[derive(Debug, PartialEq, Deserialize)] +struct FlattenStrictStrictOrSomeOtherName { + #[serde(flatten)] + data: EnumStrictStrictOrSomeOtherName, +} + +#[derive(PartialEq, Debug, Deserialize)] +#[serde(strict_or_some_other_name)] +enum EnumStrictStrictOrSomeOtherName { + Map { a: i32, b: i32, c: i32 }, +} + #[derive(PartialEq, Debug, Deserialize)] enum Enum { #[allow(dead_code)] @@ -74,6 +86,26 @@ enum EnumSkipAll { Skipped, } +#[derive(Debug, PartialEq, Deserialize)] +#[serde(tag = "type")] +#[serde(strict_or_some_other_name)] +enum InternallyTaggedStrictOrSomeOtherName { + A { a: u8 }, + B(StructStrictOrSomeOtherName), +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(tag = "type")] +enum OuterStrictOrSomeOtherName { + Inner(InnerStrictOrSomeOtherName), +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(strict_or_some_other_name)] +enum InnerStrictOrSomeOtherName { + Struct { f: u8 }, +} + #[test] fn test_i8() { let test = assert_de_tokens_error::; @@ -1262,6 +1294,63 @@ fn test_enum_out_of_range() { ); } +#[test] +fn test_struct_variant_strict_or_some_other_name_flatten() { + assert_de_tokens_error::( + &[ + Token::Map { len: None }, + Token::Str("Map"), // variant + Token::Seq { len: Some(3) }, + Token::U32(0), // a + Token::U32(42), // b + Token::U32(69), // c + Token::SeqEnd, + Token::MapEnd, + ], + "invalid type: sequence, expected struct variant EnumStrictStrictOrSomeOtherName::Map", + ); +} + +#[test] +fn test_struct_variant_strict_or_some_other_name_internally_tagged() { + assert_de_tokens_error::( + &[ + Token::Seq { len: Some(2) }, + Token::Str("A"), + Token::U8(1), + Token::SeqEnd, + ], + "invalid type: sequence, expected struct variant InternallyTaggedStrictOrSomeOtherName::A", + ); + assert_de_tokens_error::( + &[ + Token::Seq { len: Some(2) }, + Token::Str("B"), + Token::I32(0), + Token::I32(42), + Token::SeqEnd, + ], + "invalid type: sequence, expected struct StructStrictOrSomeOtherName", + ); +} + +#[test] +fn test_struct_variant_strict_or_some_other_name_enum_in_internally_tagged_enum() { + assert_de_tokens_error::( + &[ + Token::Map { len: Some(2) }, + Token::Str("type"), + Token::Str("Inner"), + Token::Str("Struct"), + Token::Seq { len: Some(1) }, + Token::U8(69), + Token::SeqEnd, + Token::MapEnd, + ], + "invalid type: sequence, expected struct variant InnerStrictOrSomeOtherName::Struct", + ); +} + #[test] fn test_short_tuple() { assert_de_tokens_error::<(u8, u8, u8)>( diff --git a/test_suite/tests/ui/strict-or-some-other-name/enum.rs b/test_suite/tests/ui/strict-or-some-other-name/enum.rs deleted file mode 100644 index 4b5a9fcfc..000000000 --- a/test_suite/tests/ui/strict-or-some-other-name/enum.rs +++ /dev/null @@ -1,9 +0,0 @@ -use serde_derive::Deserialize; - -#[derive(Deserialize)] -#[serde(strict_or_some_other_name)] -enum E { - S { a: u8 }, -} - -fn main() {} diff --git a/test_suite/tests/ui/strict-or-some-other-name/enum.stderr b/test_suite/tests/ui/strict-or-some-other-name/enum.stderr deleted file mode 100644 index 53eb7a52e..000000000 --- a/test_suite/tests/ui/strict-or-some-other-name/enum.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields - --> tests/ui/strict-or-some-other-name/enum.rs:4:9 - | -4 | #[serde(strict_or_some_other_name)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test_suite/tests/ui/strict-or-some-other-name/newtype-struct.stderr b/test_suite/tests/ui/strict-or-some-other-name/newtype-struct.stderr index 7bd680e0a..ac36cac21 100644 --- a/test_suite/tests/ui/strict-or-some-other-name/newtype-struct.stderr +++ b/test_suite/tests/ui/strict-or-some-other-name/newtype-struct.stderr @@ -1,4 +1,4 @@ -error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields +error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields or enums --> tests/ui/strict-or-some-other-name/newtype-struct.rs:4:9 | 4 | #[serde(strict_or_some_other_name)] diff --git a/test_suite/tests/ui/strict-or-some-other-name/tuple-struct.stderr b/test_suite/tests/ui/strict-or-some-other-name/tuple-struct.stderr index f8765fba5..0f96cc1ae 100644 --- a/test_suite/tests/ui/strict-or-some-other-name/tuple-struct.stderr +++ b/test_suite/tests/ui/strict-or-some-other-name/tuple-struct.stderr @@ -1,4 +1,4 @@ -error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields +error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields or enums --> tests/ui/strict-or-some-other-name/tuple-struct.rs:4:9 | 4 | #[serde(strict_or_some_other_name)] diff --git a/test_suite/tests/ui/strict-or-some-other-name/unit-struct.stderr b/test_suite/tests/ui/strict-or-some-other-name/unit-struct.stderr index e40ee33cc..091a6a0eb 100644 --- a/test_suite/tests/ui/strict-or-some-other-name/unit-struct.stderr +++ b/test_suite/tests/ui/strict-or-some-other-name/unit-struct.stderr @@ -1,4 +1,4 @@ -error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields +error: #[serde(strict_or_some_other_name)] can only be used on structs with named fields or enums --> tests/ui/strict-or-some-other-name/unit-struct.rs:4:9 | 4 | #[serde(strict_or_some_other_name)]