Merge pull request #671 from serde-rs/fields

Stop generating visit_usize and visit_bytes for FieldVisitor
This commit is contained in:
Oliver Schneider 2017-01-09 13:09:18 +01:00 committed by GitHub
commit 2b8a620807
2 changed files with 33 additions and 110 deletions

View File

@ -1,5 +1,5 @@
use syn::{self, aster}; use syn::{self, aster};
use quote::{self, Tokens}; use quote::Tokens;
use bound; use bound;
use internals::ast::{Body, Field, Item, Style, Variant}; use internals::ast::{Body, Field, Item, Style, Variant};
@ -642,7 +642,7 @@ fn deserialize_field_visitor(
is_variant: bool, is_variant: bool,
) -> Tokens { ) -> Tokens {
// Create the field names for the fields. // Create the field names for the fields.
let field_idents: Vec<_> = (0 .. field_names.len()) let ref field_idents: Vec<_> = (0 .. field_names.len())
.map(|i| aster::id(format!("__field{}", i))) .map(|i| aster::id(format!("__field{}", i)))
.collect(); .collect();
@ -652,90 +652,18 @@ fn deserialize_field_visitor(
Some(quote!(__ignore,)) Some(quote!(__ignore,))
}; };
let index_field_arms: Vec<_> = field_idents.iter() let fallthrough_arm = if is_variant {
.enumerate() quote! {
.map(|(field_index, field_ident)| { Err(_serde::de::Error::unknown_variant(value))
quote! { }
#field_index => { Ok(__Field::#field_ident) } } else if item_attrs.deny_unknown_fields() {
} quote! {
}) Err(_serde::de::Error::unknown_field(value))
.collect(); }
let (index_error_msg, unknown_ident) = if is_variant {
("expected a variant", aster::id("unknown_variant"))
} else { } else {
("expected a field", aster::id("unknown_field"))
};
let fallthrough_index_arm_expr = if !is_variant && !item_attrs.deny_unknown_fields() {
quote! { quote! {
Ok(__Field::__ignore) Ok(__Field::__ignore)
} }
} else {
quote! {
Err(_serde::de::Error::invalid_value(#index_error_msg))
}
};
let index_body = quote! {
match value {
#(#index_field_arms)*
_ => #fallthrough_index_arm_expr
}
};
// Match arms to extract a field from a string
let str_field_arms: Vec<_> = field_idents.iter().zip(field_names.iter())
.map(|(field_ident, field_name)| {
quote! {
#field_name => { Ok(__Field::#field_ident) }
}
})
.collect();
let fallthrough_str_arm_expr = if !is_variant && !item_attrs.deny_unknown_fields() {
quote! {
Ok(__Field::__ignore)
}
} else {
quote! {
Err(_serde::de::Error::#unknown_ident(value))
}
};
let str_body = quote! {
match value {
#(#str_field_arms)*
_ => #fallthrough_str_arm_expr
}
};
// Match arms to extract a field from a string
let bytes_field_arms: Vec<_> = field_idents.iter().zip(field_names.iter())
.map(|(field_ident, field_name)| {
let bytes_field_name = quote::ByteStr(field_name);
quote! {
#bytes_field_name => { Ok(__Field::#field_ident) }
}
})
.collect();
let fallthrough_bytes_arm_expr = if !is_variant && !item_attrs.deny_unknown_fields() {
quote! {
Ok(__Field::__ignore)
}
} else {
quote!({
let value = ::std::string::String::from_utf8_lossy(value);
Err(_serde::de::Error::#unknown_ident(&value))
})
};
let bytes_body = quote! {
match value {
#(#bytes_field_arms)*
_ => #fallthrough_bytes_arm_expr
}
}; };
quote! { quote! {
@ -755,22 +683,15 @@ fn deserialize_field_visitor(
impl _serde::de::Visitor for __FieldVisitor { impl _serde::de::Visitor for __FieldVisitor {
type Value = __Field; type Value = __Field;
fn visit_usize<__E>(&mut self, value: usize) -> ::std::result::Result<__Field, __E>
where __E: _serde::de::Error
{
#index_body
}
fn visit_str<__E>(&mut self, value: &str) -> ::std::result::Result<__Field, __E> fn visit_str<__E>(&mut self, value: &str) -> ::std::result::Result<__Field, __E>
where __E: _serde::de::Error where __E: _serde::de::Error
{ {
#str_body match value {
} #(
#field_names => Ok(__Field::#field_idents),
fn visit_bytes<__E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, __E> )*
where __E: _serde::de::Error _ => #fallthrough_arm
{ }
#bytes_body
} }
} }

View File

@ -3,7 +3,7 @@ use std::net;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use serde::Deserialize; use serde::de::{Deserialize, Type};
extern crate fnv; extern crate fnv;
use self::fnv::FnvHasher; use self::fnv::FnvHasher;
@ -723,20 +723,6 @@ 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)],
} }
@ -847,4 +833,20 @@ declare_error_tests! {
], ],
Error::DuplicateField("a"), Error::DuplicateField("a"),
} }
test_enum_unit_usize<Enum> {
&[
Token::EnumStart("Enum"),
Token::Usize(0),
Token::Unit,
],
Error::InvalidType(Type::U64),
}
test_enum_unit_bytes<Enum> {
&[
Token::EnumStart("Enum"),
Token::Bytes(b"Unit"),
Token::Unit,
],
Error::InvalidType(Type::Bytes),
}
} }