Merge pull request 1914 from Mingun/seq-other

This commit is contained in:
David Tolnay
2021-01-23 19:45:15 -08:00
11 changed files with 216 additions and 63 deletions
+3 -3
View File
@@ -2547,12 +2547,12 @@ pub trait IdentifierDeserializer<'de, E: Error> {
fn borrowed(self) -> Self::BorrowedDeserializer; fn borrowed(self) -> Self::BorrowedDeserializer;
} }
impl<'de, E> IdentifierDeserializer<'de, E> for u32 impl<'de, E> IdentifierDeserializer<'de, E> for u64
where where
E: Error, E: Error,
{ {
type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer; type Deserializer = <u64 as IntoDeserializer<'de, E>>::Deserializer;
type BorrowedDeserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer; type BorrowedDeserializer = <u64 as IntoDeserializer<'de, E>>::Deserializer;
fn from(self) -> Self::Deserializer { fn from(self) -> Self::Deserializer {
self.into_deserializer() self.into_deserializer()
+20 -6
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( fn deserialize_custom_identifier(
params: &Parameters, params: &Parameters,
variants: &[Variant], variants: &[Variant],
@@ -1982,6 +1984,9 @@ fn deserialize_custom_identifier(
let (ordinary, fallthrough) = if let Some(last) = variants.last() { let (ordinary, fallthrough) = if let Some(last) = variants.last() {
let last_ident = &last.ident; let last_ident = &last.ident;
if last.attrs.other() { 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 ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident)); let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident));
(ordinary, Some((fallthrough.clone(), fallthrough))) (ordinary, Some((fallthrough.clone(), fallthrough)))
@@ -2137,7 +2142,8 @@ fn deserialize_identifier(
(None, None, None, None) (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 fallthrough
} else if is_variant { } else if is_variant {
let fallthrough = quote! { let fallthrough = quote! {
@@ -2151,8 +2157,19 @@ fn deserialize_identifier(
(fallthrough.clone(), fallthrough) (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 variant_indices = 0_u64..;
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
let visit_other = if collect_other_fields { let visit_other = if collect_other_fields {
quote! { quote! {
fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E> 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), #variant_indices => _serde::__private::Ok(#main_constructors),
)* )*
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => #u64_fallthrough_arm,
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
} }
} }
} }
+28
View File
@@ -168,14 +168,42 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
self.next_token(); self.next_token();
visitor.visit_str(variant) 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) => { (Token::Bytes(variant), Token::Unit) => {
self.next_token(); self.next_token();
visitor.visit_bytes(variant) 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) => { (Token::U32(variant), Token::Unit) => {
self.next_token(); self.next_token();
visitor.visit_u32(variant) visitor.visit_u32(variant)
} }
(Token::U64(variant), Token::Unit) => {
self.next_token();
visitor.visit_u64(variant)
}
(variant, Token::Unit) => unexpected!(variant), (variant, Token::Unit) => unexpected!(variant),
(variant, _) => { (variant, _) => {
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any)) visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
+2 -12
View File
@@ -614,12 +614,7 @@ const _: () = {
1u64 => _serde::__private::Ok(__Field::__field1), 1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2), 2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3), 3u64 => _serde::__private::Ok(__Field::__field3),
_ => _serde::__private::Err( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 4",
),
),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -1152,12 +1147,7 @@ const _: () = {
1u64 => _serde::__private::Ok(__Field::__field1), 1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2), 2u64 => _serde::__private::Ok(__Field::__field2),
3u64 => _serde::__private::Ok(__Field::__field3), 3u64 => _serde::__private::Ok(__Field::__field3),
_ => _serde::__private::Err( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 4",
),
),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -77,10 +77,7 @@ const _: () = {
{ {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -284,10 +281,7 @@ const _: () = {
{ {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -394,12 +394,7 @@ const _: () = {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1), 1u64 => _serde::__private::Ok(__Field::__field1),
_ => _serde::__private::Err( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 2",
),
),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -73,10 +73,7 @@ const _: () = {
{ {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -280,10 +277,7 @@ const _: () = {
{ {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
+2 -12
View File
@@ -281,12 +281,7 @@ const _: () = {
{ {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
),
),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -494,12 +489,7 @@ const _: () = {
{ {
match __value { match __value {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
_ => _serde::__private::Err( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
),
),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -100,10 +100,7 @@ const _: () = {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1), 1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2), 2u64 => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
@@ -415,10 +412,7 @@ const _: () = {
0u64 => _serde::__private::Ok(__Field::__field0), 0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1), 1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2), 2u64 => _serde::__private::Ok(__Field::__field2),
_ => _serde::__private::Err(_serde::de::Error::invalid_value( _ => _serde::__private::Ok(__Field::__ignore),
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
} }
} }
fn visit_str<__E>( fn visit_str<__E>(
+141
View File
@@ -622,6 +622,24 @@ declare_tests! {
Token::I32(2), Token::I32(2),
Token::MapEnd, 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 } => &[ Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) }, Token::Map { len: Some(3) },
Token::U32(0), Token::U32(0),
@@ -631,6 +649,34 @@ declare_tests! {
Token::I32(2), Token::I32(2),
Token::MapEnd, 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 } => &[ Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 2 }, Token::Struct { name: "Struct", len: 2 },
Token::Str("a"), Token::Str("a"),
@@ -647,6 +693,46 @@ declare_tests! {
Token::SeqEnd, 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 { test_struct_with_skip {
Struct { a: 1, b: 2, c: 0 } => &[ Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) }, Token::Map { len: Some(3) },
@@ -663,6 +749,21 @@ declare_tests! {
Token::I32(4), Token::I32(4),
Token::MapEnd, 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 } => &[ Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 2 }, Token::Struct { name: "Struct", len: 2 },
Token::Str("a"), Token::Str("a"),
@@ -780,6 +881,26 @@ declare_tests! {
Token::Str("Unit"), Token::Str("Unit"),
Token::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 { test_enum_other {
EnumOther::Other => &[ EnumOther::Other => &[
@@ -787,6 +908,26 @@ declare_tests! {
Token::Str("Foo"), Token::Str("Foo"),
Token::Unit, 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 { test_box {
Box::new(0i32) => &[Token::I32(0)], Box::new(0i32) => &[Token::I32(0)],
+13
View File
@@ -1,3 +1,4 @@
//! Tests for `#[serde(field_identifier)]` and `#[serde(variant_identifier)]`
use serde::Deserialize; use serde::Deserialize;
use serde_test::{assert_de_tokens, Token}; use serde_test::{assert_de_tokens, Token};
@@ -27,6 +28,10 @@ fn test_field_identifier() {
Bbb, 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::Str("aaa")]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]); assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
} }
@@ -42,6 +47,10 @@ fn test_unit_fallthrough() {
Other, 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")]); assert_de_tokens(&F::Other, &[Token::Str("x")]);
} }
@@ -68,5 +77,9 @@ fn test_newtype_fallthrough_generic() {
Other(T), 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")]); assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
} }