mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-13 12:31:02 +00:00
Spring cleaning
This commit is contained in:
+102
-120
@@ -1,7 +1,6 @@
|
|||||||
use syntax::ast::{
|
use syntax::ast::{
|
||||||
Ident,
|
Ident,
|
||||||
MetaItem,
|
MetaItem,
|
||||||
MetaItem_,
|
|
||||||
Item,
|
Item,
|
||||||
Expr,
|
Expr,
|
||||||
MutMutable,
|
MutMutable,
|
||||||
@@ -34,7 +33,7 @@ use syntax::ptr::P;
|
|||||||
|
|
||||||
use aster;
|
use aster;
|
||||||
|
|
||||||
use field::struct_field_strs;
|
use field;
|
||||||
|
|
||||||
pub fn expand_derive_deserialize(
|
pub fn expand_derive_deserialize(
|
||||||
cx: &mut ExtCtxt,
|
cx: &mut ExtCtxt,
|
||||||
@@ -422,25 +421,12 @@ fn deserialize_struct_named_fields(
|
|||||||
) -> P<ast::Expr> {
|
) -> P<ast::Expr> {
|
||||||
let where_clause = &trait_generics.where_clause;
|
let where_clause = &trait_generics.where_clause;
|
||||||
|
|
||||||
// Create the field names for the fields.
|
let (field_visitor, visit_map_expr) = deserialize_struct_visitor(
|
||||||
let field_names: Vec<ast::Ident> = (0 .. fields.len())
|
|
||||||
.map(|i| builder.id(format!("__field{}", i)))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let field_visitor = deserialize_field_visitor(
|
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
&field_names,
|
|
||||||
struct_def,
|
struct_def,
|
||||||
);
|
|
||||||
|
|
||||||
let visit_map_expr = deserialize_map(
|
|
||||||
cx,
|
|
||||||
builder,
|
|
||||||
struct_path,
|
struct_path,
|
||||||
&field_names,
|
|
||||||
fields,
|
fields,
|
||||||
struct_def
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let struct_name = builder.expr().str(struct_ident);
|
let struct_name = builder.expr().str(struct_ident);
|
||||||
@@ -478,86 +464,6 @@ fn deserialize_struct_named_fields(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_field_visitor(
|
|
||||||
cx: &ExtCtxt,
|
|
||||||
builder: &aster::AstBuilder,
|
|
||||||
field_names: &[ast::Ident],
|
|
||||||
struct_def: &StructDef,
|
|
||||||
) -> Vec<P<ast::Item>> {
|
|
||||||
let field_enum = builder.item()
|
|
||||||
.attr().allow(&["non_camel_case_types"])
|
|
||||||
.enum_("__Field")
|
|
||||||
.with_variants(
|
|
||||||
field_names.iter().map(|field| {
|
|
||||||
builder.variant(field).tuple().build()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Get aliases
|
|
||||||
let aliases = struct_field_strs(cx, builder, struct_def);
|
|
||||||
|
|
||||||
// Match arms to extract a field from a string
|
|
||||||
let field_arms: Vec<ast::Arm> = aliases.iter()
|
|
||||||
.zip(field_names.iter())
|
|
||||||
.map(|(alias, field)| {
|
|
||||||
quote_arm!(cx, $alias => { Ok(__Field::$field) })
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
vec![
|
|
||||||
field_enum,
|
|
||||||
|
|
||||||
quote_item!(cx,
|
|
||||||
impl ::serde::de::Deserialize for __Field {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize<S>(state: &mut S) -> Result<__Field, S::Error>
|
|
||||||
where S: ::serde::de::Deserializer,
|
|
||||||
{
|
|
||||||
struct __FieldVisitor;
|
|
||||||
|
|
||||||
impl ::serde::de::Visitor for __FieldVisitor {
|
|
||||||
type Value = __Field;
|
|
||||||
|
|
||||||
fn visit_str<E>(&mut self, value: &str) -> Result<__Field, E>
|
|
||||||
where E: ::serde::de::Error,
|
|
||||||
{
|
|
||||||
match value {
|
|
||||||
$field_arms
|
|
||||||
_ => Err(::serde::de::Error::syntax_error()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.visit(__FieldVisitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).unwrap(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_value(field: &ast::StructField) -> bool {
|
|
||||||
field.node.attrs.iter()
|
|
||||||
.any(|sa|
|
|
||||||
if let MetaItem_::MetaList(ref n, ref vals) = sa.node.value.node {
|
|
||||||
if n == &"serde" {
|
|
||||||
vals.iter()
|
|
||||||
.map(|mi|
|
|
||||||
if let MetaItem_::MetaWord(ref n) = mi.node {
|
|
||||||
n == &"default"
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
})
|
|
||||||
.any(|x| x)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_map(
|
fn deserialize_map(
|
||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
@@ -570,10 +476,10 @@ fn deserialize_map(
|
|||||||
let let_values: Vec<P<ast::Stmt>> = field_names.iter()
|
let let_values: Vec<P<ast::Stmt>> = field_names.iter()
|
||||||
.zip(struct_def.fields.iter())
|
.zip(struct_def.fields.iter())
|
||||||
.map(|(field, sf)| {
|
.map(|(field, sf)| {
|
||||||
if default_value(sf) {
|
if field::default_value(sf) {
|
||||||
quote_stmt!(
|
quote_stmt!(cx,
|
||||||
cx,
|
let mut $field = Some(::std::default::Default::default());
|
||||||
let mut $field = Some(::std::default::Default::default());)
|
)
|
||||||
} else {
|
} else {
|
||||||
quote_stmt!(cx, let mut $field = None;)
|
quote_stmt!(cx, let mut $field = None;)
|
||||||
}
|
}
|
||||||
@@ -828,31 +734,17 @@ fn deserialize_enum_variant_map(
|
|||||||
) -> P<ast::Expr> {
|
) -> P<ast::Expr> {
|
||||||
let where_clause = &trait_generics.where_clause;
|
let where_clause = &trait_generics.where_clause;
|
||||||
|
|
||||||
// Create the field names for the fields.
|
let struct_def = match variant.node.kind {
|
||||||
let field_names: Vec<ast::Ident> = (0 .. fields.len())
|
ast::VariantKind::StructVariantKind(ref struct_def) => struct_def,
|
||||||
.map(|i| builder.id(format!("__field{}", i)))
|
_ => panic!("Mismatched enum types")
|
||||||
.collect();
|
};
|
||||||
|
|
||||||
let field_visitor = deserialize_field_visitor(
|
let (field_visitor, visit_map_expr) = deserialize_struct_visitor(
|
||||||
cx,
|
|
||||||
builder,
|
|
||||||
&field_names,
|
|
||||||
match variant.node.kind {
|
|
||||||
ast::VariantKind::StructVariantKind(ref sd) => &*sd,
|
|
||||||
_ => panic!("Mismatched enum types")
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let visit_map_expr = deserialize_map(
|
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
|
struct_def,
|
||||||
variant_path,
|
variant_path,
|
||||||
&field_names,
|
|
||||||
fields,
|
fields,
|
||||||
match variant.node.kind {
|
|
||||||
ast::VariantKind::StructVariantKind(ref sd) => &*sd,
|
|
||||||
_ => panic!("Mismatched enum types")
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
@@ -875,3 +767,93 @@ fn deserialize_enum_variant_map(
|
|||||||
$state.visit_map($visitor_expr)
|
$state.visit_map($visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_field_visitor(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
field_names: &[ast::Ident],
|
||||||
|
struct_def: &StructDef,
|
||||||
|
) -> Vec<P<ast::Item>> {
|
||||||
|
let field_enum = builder.item()
|
||||||
|
.attr().allow(&["non_camel_case_types"])
|
||||||
|
.enum_("__Field")
|
||||||
|
.with_variants(
|
||||||
|
field_names.iter().map(|field| {
|
||||||
|
builder.variant(field).tuple().build()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Get aliases
|
||||||
|
let aliases = field::struct_field_strs(cx, builder, struct_def);
|
||||||
|
|
||||||
|
// Match arms to extract a field from a string
|
||||||
|
let field_arms: Vec<ast::Arm> = aliases.iter()
|
||||||
|
.zip(field_names.iter())
|
||||||
|
.map(|(alias, field)| {
|
||||||
|
quote_arm!(cx, $alias => { Ok(__Field::$field) })
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
vec![
|
||||||
|
field_enum,
|
||||||
|
|
||||||
|
quote_item!(cx,
|
||||||
|
impl ::serde::de::Deserialize for __Field {
|
||||||
|
#[inline]
|
||||||
|
fn deserialize<S>(state: &mut S) -> Result<__Field, S::Error>
|
||||||
|
where S: ::serde::de::Deserializer,
|
||||||
|
{
|
||||||
|
struct __FieldVisitor;
|
||||||
|
|
||||||
|
impl ::serde::de::Visitor for __FieldVisitor {
|
||||||
|
type Value = __Field;
|
||||||
|
|
||||||
|
fn visit_str<E>(&mut self, value: &str) -> Result<__Field, E>
|
||||||
|
where E: ::serde::de::Error,
|
||||||
|
{
|
||||||
|
match value {
|
||||||
|
$field_arms
|
||||||
|
_ => Err(::serde::de::Error::syntax_error()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.visit(__FieldVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).unwrap(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_visitor(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
struct_def: &ast::StructDef,
|
||||||
|
struct_path: ast::Path,
|
||||||
|
fields: &[Ident],
|
||||||
|
) -> (Vec<P<ast::Item>>, P<ast::Expr>) {
|
||||||
|
|
||||||
|
// Create the field names for the fields.
|
||||||
|
let field_names: Vec<ast::Ident> = (0 .. struct_def.fields.len())
|
||||||
|
.map(|i| builder.id(format!("__field{}", i)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let field_visitor = deserialize_field_visitor(
|
||||||
|
cx,
|
||||||
|
builder,
|
||||||
|
&field_names,
|
||||||
|
struct_def,
|
||||||
|
);
|
||||||
|
|
||||||
|
let visit_map_expr = deserialize_map(
|
||||||
|
cx,
|
||||||
|
builder,
|
||||||
|
struct_path,
|
||||||
|
&field_names,
|
||||||
|
fields,
|
||||||
|
struct_def,
|
||||||
|
);
|
||||||
|
|
||||||
|
(field_visitor, visit_map_expr)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use syntax::ptr::P;
|
|||||||
|
|
||||||
use aster;
|
use aster;
|
||||||
|
|
||||||
pub fn field_alias(field: &ast::StructField) -> Option<&ast::Lit> {
|
fn field_alias(field: &ast::StructField) -> Option<&ast::Lit> {
|
||||||
field.node.attrs.iter()
|
field.node.attrs.iter()
|
||||||
.find(|sa| {
|
.find(|sa| {
|
||||||
if let ast::MetaList(ref n, _) = sa.node.value.node {
|
if let ast::MetaList(ref n, _) = sa.node.value.node {
|
||||||
@@ -55,3 +55,26 @@ pub fn struct_field_strs(
|
|||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_value(field: &ast::StructField) -> bool {
|
||||||
|
field.node.attrs.iter()
|
||||||
|
.any(|sa| {
|
||||||
|
if let ast::MetaItem_::MetaList(ref n, ref vals) = sa.node.value.node {
|
||||||
|
if n == &"serde" {
|
||||||
|
vals.iter()
|
||||||
|
.map(|mi|
|
||||||
|
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
|
||||||
|
n == &"default"
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.any(|x| x)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user