Merge pull request 1914 from Mingun/seq-other

This commit is contained in:
David Tolnay 2021-01-23 19:45:15 -08:00
commit e6b6602a42
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
11 changed files with 216 additions and 63 deletions

View File

@ -2547,12 +2547,12 @@ pub trait IdentifierDeserializer<'de, E: Error> {
fn borrowed(self) -> Self::BorrowedDeserializer;
}
impl<'de, E> IdentifierDeserializer<'de, E> for u32
impl<'de, E> IdentifierDeserializer<'de, E> for u64
where
E: Error,
{
type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
type BorrowedDeserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
type Deserializer = <u64 as IntoDeserializer<'de, E>>::Deserializer;
type BorrowedDeserializer = <u64 as IntoDeserializer<'de, E>>::Deserializer;
fn from(self) -> Self::Deserializer {
self.into_deserializer()

View File

@ -1965,6 +1965,8 @@ fn deserialize_generated_identifier(
}
}
// Generates `Deserialize::deserialize` body for an enum with
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
fn deserialize_custom_identifier(
params: &Parameters,
variants: &[Variant],
@ -1982,6 +1984,9 @@ fn deserialize_custom_identifier(
let (ordinary, fallthrough) = if let Some(last) = variants.last() {
let last_ident = &last.ident;
if last.attrs.other() {
// Process `serde(other)` attribute. It would always be found on the
// last variant (checked in `check_identifier`), so all preceding
// are ordinary variants.
let ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident));
(ordinary, Some((fallthrough.clone(), fallthrough)))
@ -2137,7 +2142,8 @@ fn deserialize_identifier(
(None, None, None, None)
};
let (fallthrough_arm, fallthrough_borrowed_arm) = if let Some(fallthrough) = fallthrough {
let (fallthrough_arm, fallthrough_borrowed_arm) = if let Some(fallthrough) = fallthrough.clone()
{
fallthrough
} else if is_variant {
let fallthrough = quote! {
@ -2151,8 +2157,19 @@ fn deserialize_identifier(
(fallthrough.clone(), fallthrough)
};
let u64_fallthrough_arm = if let Some((fallthrough, _)) = fallthrough {
fallthrough
} else {
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
quote! {
_serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
}
};
let variant_indices = 0_u64..;
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
let visit_other = if collect_other_fields {
quote! {
fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E>
@ -2256,10 +2273,7 @@ fn deserialize_identifier(
#(
#variant_indices => _serde::__private::Ok(#main_constructors),
)*
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
_ => #u64_fallthrough_arm,
}
}
}

View File

@ -168,14 +168,42 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
self.next_token();
visitor.visit_str(variant)
}
(Token::BorrowedStr(variant), Token::Unit) => {
self.next_token();
visitor.visit_borrowed_str(variant)
}
(Token::String(variant), Token::Unit) => {
self.next_token();
visitor.visit_string(variant.to_string())
}
(Token::Bytes(variant), Token::Unit) => {
self.next_token();
visitor.visit_bytes(variant)
}
(Token::BorrowedBytes(variant), Token::Unit) => {
self.next_token();
visitor.visit_borrowed_bytes(variant)
}
(Token::ByteBuf(variant), Token::Unit) => {
self.next_token();
visitor.visit_byte_buf(variant.to_vec())
}
(Token::U8(variant), Token::Unit) => {
self.next_token();
visitor.visit_u8(variant)
}
(Token::U16(variant), Token::Unit) => {
self.next_token();
visitor.visit_u16(variant)
}
(Token::U32(variant), Token::Unit) => {
self.next_token();
visitor.visit_u32(variant)
}
(Token::U64(variant), Token::Unit) => {
self.next_token();
visitor.visit_u64(variant)
}
(variant, Token::Unit) => unexpected!(variant),
(variant, _) => {
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))

View File

@ -614,12 +614,7 @@ const _: () = {
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3),
_ => _serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 4",
),
),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
@ -1152,12 +1147,7 @@ const _: () = {
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3),
_ => _serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 4",
),
),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(

View File

@ -77,10 +77,7 @@ const _: () = {
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
@ -284,10 +281,7 @@ const _: () = {
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(

View File

@ -394,12 +394,7 @@ const _: () = {
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
_ => _serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 2",
),
),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(

View File

@ -73,10 +73,7 @@ const _: () = {
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
@ -280,10 +277,7 @@ const _: () = {
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(

View File

@ -281,12 +281,7 @@ const _: () = {
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
),
),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
@ -494,12 +489,7 @@ const _: () = {
{
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
),
),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(

View File

@ -100,10 +100,7 @@ const _: () = {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
@ -415,10 +412,7 @@ const _: () = {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
_ => _serde::__private::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(

View File

@ -622,6 +622,24 @@ declare_tests! {
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U8(0),
Token::I32(1),
Token::U8(1),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U16(0),
Token::I32(1),
Token::U16(1),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U32(0),
@ -631,6 +649,34 @@ declare_tests! {
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U64(0),
Token::I32(1),
Token::U64(1),
Token::I32(2),
Token::MapEnd,
],
// Mixed key types
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U8(0),
Token::I32(1),
Token::U64(1),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U8(0),
Token::I32(1),
Token::Str("b"),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 2 },
Token::Str("a"),
@ -647,6 +693,46 @@ declare_tests! {
Token::SeqEnd,
],
}
test_struct_borrowed_keys {
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::BorrowedStr("a"),
Token::I32(1),
Token::BorrowedStr("b"),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 2 },
Token::BorrowedStr("a"),
Token::I32(1),
Token::BorrowedStr("b"),
Token::I32(2),
Token::StructEnd,
],
}
test_struct_owned_keys {
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::String("a"),
Token::I32(1),
Token::String("b"),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 2 },
Token::String("a"),
Token::I32(1),
Token::String("b"),
Token::I32(2),
Token::StructEnd,
],
}
test_struct_with_skip {
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
@ -663,6 +749,21 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U8(0),
Token::I32(1),
Token::U16(1),
Token::I32(2),
Token::U32(2),
Token::I32(3),
Token::U64(3),
Token::I32(4),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 2 },
Token::Str("a"),
@ -780,6 +881,26 @@ declare_tests! {
Token::Str("Unit"),
Token::Unit,
],
EnumOther::Unit => &[
Token::Enum { name: "EnumOther" },
Token::U8(0),
Token::Unit,
],
EnumOther::Unit => &[
Token::Enum { name: "EnumOther" },
Token::U16(0),
Token::Unit,
],
EnumOther::Unit => &[
Token::Enum { name: "EnumOther" },
Token::U32(0),
Token::Unit,
],
EnumOther::Unit => &[
Token::Enum { name: "EnumOther" },
Token::U64(0),
Token::Unit,
],
}
test_enum_other {
EnumOther::Other => &[
@ -787,6 +908,26 @@ declare_tests! {
Token::Str("Foo"),
Token::Unit,
],
EnumOther::Other => &[
Token::Enum { name: "EnumOther" },
Token::U8(42),
Token::Unit,
],
EnumOther::Other => &[
Token::Enum { name: "EnumOther" },
Token::U16(42),
Token::Unit,
],
EnumOther::Other => &[
Token::Enum { name: "EnumOther" },
Token::U32(42),
Token::Unit,
],
EnumOther::Other => &[
Token::Enum { name: "EnumOther" },
Token::U64(42),
Token::Unit,
],
}
test_box {
Box::new(0i32) => &[Token::I32(0)],

View File

@ -1,3 +1,4 @@
//! Tests for `#[serde(field_identifier)]` and `#[serde(variant_identifier)]`
use serde::Deserialize;
use serde_test::{assert_de_tokens, Token};
@ -27,6 +28,10 @@ fn test_field_identifier() {
Bbb,
}
assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
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")]);
}
@ -42,6 +47,10 @@ fn test_unit_fallthrough() {
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")]);
}
@ -68,5 +77,9 @@ fn test_newtype_fallthrough_generic() {
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")]);
}