Merge pull request 2475 from Baptistemontan/master

This commit is contained in:
David Tolnay 2023-07-08 18:02:16 -07:00
commit 7aa0453c3b
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 600 additions and 2 deletions
serde/src/private
test_suite/tests

@ -894,7 +894,7 @@ mod content {
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
deserializer.deserialize_identifier(self)
}
}
@ -905,6 +905,20 @@ mod content {
write!(formatter, "{:?} or {:?}", self.tag, self.content)
}
fn visit_u64<E>(self, field_index: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
match field_index {
0 => Ok(TagOrContentField::Tag),
1 => Ok(TagOrContentField::Content),
_ => Err(de::Error::invalid_value(
Unexpected::Unsigned(field_index),
&self,
)),
}
}
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
where
E: de::Error,
@ -917,6 +931,19 @@ mod content {
Err(de::Error::invalid_value(Unexpected::Str(field), &self))
}
}
fn visit_bytes<E>(self, field: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
if field == self.tag.as_bytes() {
Ok(TagOrContentField::Tag)
} else if field == self.content.as_bytes() {
Ok(TagOrContentField::Content)
} else {
Err(de::Error::invalid_value(Unexpected::Bytes(field), &self))
}
}
}
/// Used by generated code to deserialize an adjacently tagged enum when
@ -942,7 +969,7 @@ mod content {
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
deserializer.deserialize_identifier(self)
}
}
@ -957,6 +984,17 @@ mod content {
)
}
fn visit_u64<E>(self, field_index: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
match field_index {
0 => Ok(TagContentOtherField::Tag),
1 => Ok(TagContentOtherField::Content),
_ => Ok(TagContentOtherField::Other),
}
}
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
where
E: de::Error,

@ -1086,6 +1086,34 @@ fn test_adjacently_tagged_enum() {
],
);
// unit with no content (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::StructEnd,
],
);
// unit with no content (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::StructEnd,
],
);
// unit with tag first
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
@ -1102,6 +1130,38 @@ fn test_adjacently_tagged_enum() {
],
);
// unit with tag first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::U64(1), // content field
Token::Unit,
Token::StructEnd,
],
);
// unit with tag first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::Bytes(b"c"),
Token::Unit,
Token::StructEnd,
],
);
// unit with content first
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
@ -1118,6 +1178,38 @@ fn test_adjacently_tagged_enum() {
],
);
// unit with content first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(1), // content field
Token::Unit,
Token::U64(0), // tag field
Token::Str("Unit"),
Token::StructEnd,
],
);
// unit with content first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"c"),
Token::Unit,
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::StructEnd,
],
);
// unit with excess content (f, g, h)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
@ -1140,6 +1232,50 @@ fn test_adjacently_tagged_enum() {
],
);
// unit with excess content (f, g, 3) (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Str("f"),
Token::Unit,
Token::U64(0), // tag field
Token::Str("Unit"),
Token::Str("g"),
Token::Unit,
Token::U64(1), // content field
Token::Unit,
Token::U64(3), // unknown field
Token::Unit,
Token::StructEnd,
],
);
// unit with excess content (f, b"g", 3) (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Unit::<u8>,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Str("f"),
Token::Unit,
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::Bytes(b"g"),
Token::Unit,
Token::Str("c"),
Token::Unit,
Token::U64(3),
Token::Unit,
Token::StructEnd,
],
);
// newtype with tag first
assert_tokens(
&AdjacentlyTagged::Newtype::<u8>(1),
@ -1156,6 +1292,38 @@ fn test_adjacently_tagged_enum() {
],
);
// newtype with tag first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Newtype::<u8>(1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Newtype"),
Token::U64(1), // content field
Token::U8(1),
Token::StructEnd,
],
);
// newtype with tag first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Newtype::<u8>(1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Newtype"),
Token::Bytes(b"c"),
Token::U8(1),
Token::StructEnd,
],
);
// newtype with content first
assert_de_tokens(
&AdjacentlyTagged::Newtype::<u8>(1),
@ -1172,6 +1340,38 @@ fn test_adjacently_tagged_enum() {
],
);
// newtype with content first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Newtype::<u8>(1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(1), // content field
Token::U8(1),
Token::U64(0), // tag field
Token::Str("Newtype"),
Token::StructEnd,
],
);
// newtype with content first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Newtype::<u8>(1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"c"),
Token::U8(1),
Token::Bytes(b"t"),
Token::Str("Newtype"),
Token::StructEnd,
],
);
// optional newtype with no content field
assert_de_tokens(
&AdjacentlyTagged::Newtype::<Option<u8>>(None),
@ -1186,6 +1386,34 @@ fn test_adjacently_tagged_enum() {
],
);
// optional newtype with no content field (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Newtype::<Option<u8>>(None),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 1,
},
Token::U64(0), // tag field
Token::Str("Newtype"),
Token::StructEnd,
],
);
// optional newtype with no content field (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Newtype::<Option<u8>>(None),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 1,
},
Token::Bytes(b"t"),
Token::Str("Newtype"),
Token::StructEnd,
],
);
// tuple with tag first
assert_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
@ -1205,6 +1433,44 @@ fn test_adjacently_tagged_enum() {
],
);
// tuple with tag first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Tuple"),
Token::U64(1), // content field
Token::Tuple { len: 2 },
Token::U8(1),
Token::U8(1),
Token::TupleEnd,
Token::StructEnd,
],
);
// tuple with tag first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Tuple"),
Token::Bytes(b"c"),
Token::Tuple { len: 2 },
Token::U8(1),
Token::U8(1),
Token::TupleEnd,
Token::StructEnd,
],
);
// tuple with content first
assert_de_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
@ -1224,6 +1490,44 @@ fn test_adjacently_tagged_enum() {
],
);
// tuple with content first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(1), // content field
Token::Tuple { len: 2 },
Token::U8(1),
Token::U8(1),
Token::TupleEnd,
Token::U64(0), // tag field
Token::Str("Tuple"),
Token::StructEnd,
],
);
// tuple with content first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"c"),
Token::Tuple { len: 2 },
Token::U8(1),
Token::U8(1),
Token::TupleEnd,
Token::Bytes(b"t"),
Token::Str("Tuple"),
Token::StructEnd,
],
);
// struct with tag first
assert_tokens(
&AdjacentlyTagged::Struct::<u8> { f: 1 },
@ -1246,6 +1550,50 @@ fn test_adjacently_tagged_enum() {
],
);
// struct with tag first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Struct::<u8> { f: 1 },
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Struct"),
Token::U64(1), // content field
Token::Struct {
name: "Struct",
len: 1,
},
Token::Str("f"),
Token::U8(1),
Token::StructEnd,
Token::StructEnd,
],
);
// struct with tag first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Struct::<u8> { f: 1 },
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Struct"),
Token::Bytes(b"c"),
Token::Struct {
name: "Struct",
len: 1,
},
Token::Str("f"),
Token::U8(1),
Token::StructEnd,
Token::StructEnd,
],
);
// struct with content first
assert_de_tokens(
&AdjacentlyTagged::Struct::<u8> { f: 1 },
@ -1267,6 +1615,50 @@ fn test_adjacently_tagged_enum() {
Token::StructEnd,
],
);
// struct with content first (integer tag)
assert_de_tokens(
&AdjacentlyTagged::Struct::<u8> { f: 1 },
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(1), // content field
Token::Struct {
name: "Struct",
len: 1,
},
Token::Str("f"),
Token::U8(1),
Token::StructEnd,
Token::U64(0), // tag field
Token::Str("Struct"),
Token::StructEnd,
],
);
// struct with content first (bytes tag)
assert_de_tokens(
&AdjacentlyTagged::Struct::<u8> { f: 1 },
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"c"),
Token::Struct {
name: "Struct",
len: 1,
},
Token::Str("f"),
Token::U8(1),
Token::StructEnd,
Token::Bytes(b"t"),
Token::Str("Struct"),
Token::StructEnd,
],
);
}
#[test]
@ -1292,6 +1684,126 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::U64(1), // content field
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::Bytes(b"c"),
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Str("t"),
Token::Str("Unit"),
Token::U64(1), // content field
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::Str("c"),
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::U64(1), // content field
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::Str("c"),
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Str("c"),
Token::Unit,
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Str("c"),
Token::Unit,
Token::Bytes(b"t"),
Token::Str("Unit"),
Token::StructEnd,
],
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
@ -1330,6 +1842,54 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
],
r#"invalid value: string "h", expected "t" or "c""#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(2),
],
r#"invalid value: integer `2`, expected "t" or "c""#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0), // tag field
Token::Str("Unit"),
Token::U64(3),
],
r#"invalid value: integer `3`, expected "t" or "c""#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"h"),
],
r#"invalid value: byte array, expected "t" or "c""#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"c"),
Token::Unit,
Token::Bytes(b"h"),
],
r#"invalid value: byte array, expected "t" or "c""#,
);
}
#[test]