Skip to content

Commit

Permalink
Allow field identifiers be any numbers if #[serde(other)] is used
Browse files Browse the repository at this point in the history
Thus behavior synchronized between string/bytes identifiers and numeric identifiers
  • Loading branch information
Mingun committed Oct 22, 2020
1 parent 34de1e0 commit 0737474
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 50 deletions.
37 changes: 31 additions & 6 deletions serde_derive/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,6 +1940,15 @@ fn deserialize_generated_identifier(
}
}

/// Generates `Deserialize::deserialize` body for
/// ```ignore
/// #[serde(field_identifier)]
/// enum Field {
/// }
/// #[serde(variant_identifier)]
/// enum Variant {
/// }
/// ```
fn deserialize_custom_identifier(
params: &Parameters,
variants: &[Variant],
Expand All @@ -1957,6 +1966,8 @@ fn deserialize_custom_identifier(
let (ordinary, fallthrough) = if let Some(last) = variants.last() {
let last_ident = &last.ident;
if last.attrs.other() {
// Processes `#[serde(other)]` attribute. It always belongs to the last variant
// (checked in `check_identifier`), so all other are ordinal variants
let ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::export::Ok(#this::#last_ident));
(ordinary, Some(fallthrough))
Expand All @@ -1976,6 +1987,10 @@ fn deserialize_custom_identifier(
(variants, None)
};

// List of tuples:
// - field or variant name in the expected messages
// - information about field/variant
// - list of alternate names of the field/variant
let names_idents: Vec<_> = ordinary
.iter()
.map(|variant| {
Expand Down Expand Up @@ -2106,7 +2121,7 @@ fn deserialize_identifier(
(None, None, None, None)
};

let fallthrough_arm = if let Some(fallthrough) = fallthrough {
let fallthrough_arm = if let Some(fallthrough) = fallthrough.clone() {
fallthrough
} else if is_variant {
quote! {
Expand All @@ -2118,8 +2133,19 @@ fn deserialize_identifier(
}
};

let u64_fallthrough_arm = if let Some(fallthrough) = fallthrough {
fallthrough
} else {
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
quote! {
_serde::export::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::export::Result<Self::Value, __E>
Expand Down Expand Up @@ -2254,10 +2280,9 @@ fn deserialize_identifier(
#(
#variant_indices => _serde::export::Ok(#main_constructors),
)*
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
_ => {
#u64_fallthrough_arm
}
}
}
}
Expand Down
10 changes: 2 additions & 8 deletions test_suite/tests/expand/de_enum.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,10 +563,7 @@ const _: () = {
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
3u64 => _serde::export::Ok(__Field::__field3),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 4",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
Expand Down Expand Up @@ -1066,10 +1063,7 @@ const _: () = {
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
3u64 => _serde::export::Ok(__Field::__field3),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 4",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
Expand Down
10 changes: 2 additions & 8 deletions test_suite/tests/expand/default_ty_param.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,7 @@ const _: () = {
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
Expand Down Expand Up @@ -250,10 +247,7 @@ const _: () = {
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
Expand Down
5 changes: 1 addition & 4 deletions test_suite/tests/expand/generic_enum.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,7 @@ const _: () = {
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 2",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
Expand Down
10 changes: 2 additions & 8 deletions test_suite/tests/expand/generic_struct.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,7 @@ const _: () = {
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
Expand Down Expand Up @@ -246,10 +243,7 @@ const _: () = {
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
Expand Down
10 changes: 2 additions & 8 deletions test_suite/tests/expand/lifetimes.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,7 @@ const _: () = {
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
Expand Down Expand Up @@ -420,10 +417,7 @@ const _: () = {
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(
Expand Down
10 changes: 2 additions & 8 deletions test_suite/tests/expand/named_map.expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,7 @@ const _: () = {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
Expand Down Expand Up @@ -373,10 +370,7 @@ const _: () = {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
Expand Down

0 comments on commit 0737474

Please sign in to comment.