Adjancently tagged enum field is determined with visit_identifier instead of only visit_str

This commit is contained in:
Baptiste de Montangon
2023-06-12 15:27:28 +02:00
parent 8a4dfa7231
commit b1c7db47b8
2 changed files with 609 additions and 7 deletions
+46 -4
View File
@@ -915,7 +915,7 @@ mod content {
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
deserializer.deserialize_identifier(self)
}
}
@@ -923,7 +923,25 @@ mod content {
type Value = TagOrContentField;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{:?} or {:?}", self.tag, self.content)
write!(
formatter,
"{:?}, {:?}, b{0:?}, b{1:?}, 0 or 1",
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>
@@ -938,6 +956,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
@@ -963,7 +994,7 @@ mod content {
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
deserializer.deserialize_identifier(self)
}
}
@@ -973,11 +1004,22 @@ mod content {
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"{:?}, {:?}, or other ignored fields",
"{:?}, {:?}, b{0:?}, b{1:?}, 0, 1, or other ignored field identifiers",
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(TagContentOtherField::Tag),
1 => Ok(TagContentOtherField::Content),
_ => Ok(TagContentOtherField::Other),
}
}
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
where
E: de::Error,
+563 -3
View File
@@ -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),
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),
Token::Str("Unit"),
Token::U64(1),
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),
Token::Unit,
Token::U64(0),
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),
Token::Str("Unit"),
Token::Str("g"),
Token::Unit,
Token::U64(1),
Token::Unit,
Token::U64(3),
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),
Token::Str("Newtype"),
Token::U64(1),
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),
Token::U8(1),
Token::U64(0),
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),
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),
Token::Str("Tuple"),
Token::U64(1),
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),
Token::Tuple { len: 2 },
Token::U8(1),
Token::U8(1),
Token::TupleEnd,
Token::U64(0),
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),
Token::Str("Struct"),
Token::U64(1),
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),
Token::Struct {
name: "Struct",
len: 1,
},
Token::Str("f"),
Token::U8(1),
Token::StructEnd,
Token::U64(0),
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),
Token::Str("Unit"),
Token::U64(1),
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),
Token::Unit,
Token::StructEnd,
],
);
assert_de_tokens(
&AdjacentlyTagged::Unit,
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0),
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),
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 {
@@ -1304,7 +1816,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
Token::Unit,
Token::Str("h"),
],
r#"invalid value: string "h", expected "t" or "c""#,
r#"invalid value: string "h", expected "t", "c", b"t", b"c", 0 or 1"#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
@@ -1315,7 +1827,7 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
},
Token::Str("h"),
],
r#"invalid value: string "h", expected "t" or "c""#,
r#"invalid value: string "h", expected "t", "c", b"t", b"c", 0 or 1"#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
@@ -1328,7 +1840,55 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
Token::Unit,
Token::Str("h"),
],
r#"invalid value: string "h", expected "t" or "c""#,
r#"invalid value: string "h", expected "t", "c", b"t", b"c", 0 or 1"#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(2),
],
r#"invalid value: integer `2`, expected "t", "c", b"t", b"c", 0 or 1"#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::U64(0),
Token::Str("Unit"),
Token::U64(3),
],
r#"invalid value: integer `3`, expected "t", "c", b"t", b"c", 0 or 1"#,
);
assert_de_tokens_error::<AdjacentlyTagged>(
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 2,
},
Token::Bytes(b"h"),
],
r#"invalid value: byte array, expected "t", "c", b"t", b"c", 0 or 1"#,
);
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", "c", b"t", b"c", 0 or 1"#,
);
}