mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-07-24 13:35:46 +00:00
Merge pull request #700 from serde-rs/usize
Restore visit_usize and visit_bytes for identifying variants
This commit is contained in:
+51
-3
@@ -1,5 +1,5 @@
|
|||||||
use syn::{self, aster, Ident};
|
use syn::{self, aster, Ident};
|
||||||
use quote::Tokens;
|
use quote::{self, Tokens};
|
||||||
|
|
||||||
use bound;
|
use bound;
|
||||||
use internals::ast::{Body, Field, Item, Style, Variant};
|
use internals::ast::{Body, Field, Item, Style, Variant};
|
||||||
@@ -682,7 +682,8 @@ fn deserialize_field_visitor(
|
|||||||
item_attrs: &attr::Item,
|
item_attrs: &attr::Item,
|
||||||
is_variant: bool,
|
is_variant: bool,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
let field_names = fields.iter().map(|&(ref name, _)| name);
|
let field_strs = fields.iter().map(|&(ref name, _)| name);
|
||||||
|
let field_bytes = fields.iter().map(|&(ref name, _)| quote::ByteStr(name));
|
||||||
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
|
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
|
||||||
|
|
||||||
let ignore_variant = if is_variant || item_attrs.deny_unknown_fields() {
|
let ignore_variant = if is_variant || item_attrs.deny_unknown_fields() {
|
||||||
@@ -691,6 +692,27 @@ fn deserialize_field_visitor(
|
|||||||
Some(quote!(__ignore,))
|
Some(quote!(__ignore,))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let visit_usize = if is_variant {
|
||||||
|
let variant_indices = 0usize..;
|
||||||
|
let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len());
|
||||||
|
Some(quote! {
|
||||||
|
fn visit_usize<__E>(self, value: usize) -> ::std::result::Result<__Field, __E>
|
||||||
|
where __E: _serde::de::Error
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
#(
|
||||||
|
#variant_indices => Ok(__Field::#field_idents),
|
||||||
|
)*
|
||||||
|
_ => Err(_serde::de::Error::invalid_value(
|
||||||
|
_serde::de::Unexpected::Unsigned(value as u64),
|
||||||
|
&#fallthrough_msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let fallthrough_arm = if is_variant {
|
let fallthrough_arm = if is_variant {
|
||||||
quote! {
|
quote! {
|
||||||
Err(_serde::de::Error::unknown_variant(value, VARIANTS))
|
Err(_serde::de::Error::unknown_variant(value, VARIANTS))
|
||||||
@@ -705,6 +727,16 @@ fn deserialize_field_visitor(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let bytes_to_str = if is_variant || item_attrs.deny_unknown_fields() {
|
||||||
|
Some(quote! {
|
||||||
|
// TODO https://github.com/serde-rs/serde/issues/666
|
||||||
|
// update this to use str::from_utf8(value).unwrap_or("���") on no_std
|
||||||
|
let value = &::std::string::String::from_utf8_lossy(value);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
enum __Field {
|
enum __Field {
|
||||||
@@ -726,16 +758,32 @@ fn deserialize_field_visitor(
|
|||||||
formatter.write_str("field name")
|
formatter.write_str("field name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#visit_usize
|
||||||
|
|
||||||
fn visit_str<__E>(self, value: &str) -> ::std::result::Result<__Field, __E>
|
fn visit_str<__E>(self, value: &str) -> ::std::result::Result<__Field, __E>
|
||||||
where __E: _serde::de::Error
|
where __E: _serde::de::Error
|
||||||
{
|
{
|
||||||
match value {
|
match value {
|
||||||
#(
|
#(
|
||||||
#field_names => Ok(__Field::#field_idents),
|
#field_strs => Ok(__Field::#field_idents),
|
||||||
)*
|
)*
|
||||||
_ => #fallthrough_arm
|
_ => #fallthrough_arm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<__E>(self, value: &[u8]) -> ::std::result::Result<__Field, __E>
|
||||||
|
where __E: _serde::de::Error
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
#(
|
||||||
|
#field_bytes => Ok(__Field::#field_idents),
|
||||||
|
)*
|
||||||
|
_ => {
|
||||||
|
#bytes_to_str
|
||||||
|
#fallthrough_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.deserialize_struct_field(__FieldVisitor)
|
deserializer.deserialize_struct_field(__FieldVisitor)
|
||||||
|
|||||||
+17
-11
@@ -774,6 +774,20 @@ declare_tests! {
|
|||||||
Token::EnumMapEnd,
|
Token::EnumMapEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_enum_unit_usize {
|
||||||
|
Enum::Unit => &[
|
||||||
|
Token::EnumStart("Enum"),
|
||||||
|
Token::Usize(0),
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
test_enum_unit_bytes {
|
||||||
|
Enum::Unit => &[
|
||||||
|
Token::EnumStart("Enum"),
|
||||||
|
Token::Bytes(b"Unit"),
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_box {
|
test_box {
|
||||||
Box::new(0i32) => &[Token::I32(0)],
|
Box::new(0i32) => &[Token::I32(0)],
|
||||||
}
|
}
|
||||||
@@ -918,20 +932,12 @@ declare_error_tests! {
|
|||||||
],
|
],
|
||||||
Error::Message("duplicate field `a`".to_owned()),
|
Error::Message("duplicate field `a`".to_owned()),
|
||||||
}
|
}
|
||||||
test_enum_unit_usize<Enum> {
|
test_enum_out_of_range<Enum> {
|
||||||
&[
|
&[
|
||||||
Token::EnumStart("Enum"),
|
Token::EnumStart("Enum"),
|
||||||
Token::Usize(0),
|
Token::Usize(4),
|
||||||
Token::Unit,
|
Token::Unit,
|
||||||
],
|
],
|
||||||
Error::Message("invalid type: integer `0`, expected field name".into()),
|
Error::Message("invalid value: integer `4`, expected variant index 0 <= i < 4".into()),
|
||||||
}
|
|
||||||
test_enum_unit_bytes<Enum> {
|
|
||||||
&[
|
|
||||||
Token::EnumStart("Enum"),
|
|
||||||
Token::Bytes(b"Unit"),
|
|
||||||
Token::Unit,
|
|
||||||
],
|
|
||||||
Error::Message("invalid type: byte array, expected field name".into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user