Cleanup, and move default::Default #[derive_deserialize] support to get called when missing

This commit is contained in:
Erick Tryzelaar
2015-03-15 18:37:26 -07:00
parent 9fc9d1b33a
commit 90e02206fe
+47 -70
View File
@@ -10,7 +10,6 @@ use syntax::ast;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt; use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder; use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P; use syntax::ptr::P;
use aster; use aster;
@@ -142,7 +141,6 @@ fn deserialize_item_struct(
impl_generics, impl_generics,
ty, ty,
struct_def, struct_def,
named_fields,
) )
} }
(false, false) => { (false, false) => {
@@ -242,10 +240,6 @@ fn deserialize_tuple_struct(
) -> P<ast::Expr> { ) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause; let where_clause = &impl_generics.where_clause;
let field_names: Vec<ast::Ident> = (0 .. fields)
.map(|i| builder.id(&format!("__field{}", i)))
.collect();
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor( let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder, builder,
impl_generics, impl_generics,
@@ -255,7 +249,7 @@ fn deserialize_tuple_struct(
cx, cx,
builder, builder,
builder.path().id(type_ident).build(), builder.path().id(type_ident).build(),
&field_names, fields,
); );
let type_name = builder.expr().str(type_ident); let type_name = builder.expr().str(type_ident);
@@ -293,10 +287,11 @@ fn deserialize_seq(
cx: &ExtCtxt, cx: &ExtCtxt,
builder: &aster::AstBuilder, builder: &aster::AstBuilder,
struct_path: ast::Path, struct_path: ast::Path,
field_names: &[Ident], fields: usize,
) -> P<ast::Expr> { ) -> P<ast::Expr> {
let let_values: Vec<P<ast::Stmt>> = field_names.iter() let let_values: Vec<P<_>> = (0 .. fields)
.map(|name| { .map(|i| {
let name = builder.id(format!("__field{}", i));
quote_stmt!(cx, quote_stmt!(cx,
let $name = match try!(visitor.visit()) { let $name = match try!(visitor.visit()) {
Some(value) => value, Some(value) => value,
@@ -310,7 +305,7 @@ fn deserialize_seq(
let result = builder.expr().call() let result = builder.expr().call()
.build_path(struct_path) .build_path(struct_path)
.with_args(field_names.iter().map(|name| builder.expr().id(*name))) .with_args((0 .. fields).map(|i| builder.expr().id(format!("__field{}", i))))
.build(); .build();
quote_expr!(cx, { quote_expr!(cx, {
@@ -329,7 +324,6 @@ fn deserialize_struct(
impl_generics: &ast::Generics, impl_generics: &ast::Generics,
ty: P<ast::Ty>, ty: P<ast::Ty>,
struct_def: &StructDef, struct_def: &StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> { ) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause; let where_clause = &impl_generics.where_clause;
@@ -343,7 +337,6 @@ fn deserialize_struct(
builder, builder,
struct_def, struct_def,
builder.path().id(type_ident).build(), builder.path().id(type_ident).build(),
fields,
); );
let type_name = builder.expr().str(type_ident); let type_name = builder.expr().str(type_ident);
@@ -385,41 +378,47 @@ fn deserialize_map(
cx: &ExtCtxt, cx: &ExtCtxt,
builder: &aster::AstBuilder, builder: &aster::AstBuilder,
struct_path: ast::Path, struct_path: ast::Path,
field_names: &[Ident],
fields: Vec<Ident>,
struct_def: &StructDef, struct_def: &StructDef,
) -> P<ast::Expr> { ) -> 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();
// Declare each field. // Declare each field.
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()) .map(|field_name| quote_stmt!(cx, let mut $field_name = None;))
.map(|(field, sf)| {
if field::default_value(sf) {
quote_stmt!(cx,
let mut $field = Some(::std::default::Default::default());
)
} else {
quote_stmt!(cx, let mut $field = None;)
}
})
.collect(); .collect();
// Match arms to extract a value for a field. // Match arms to extract a value for a field.
let value_arms: Vec<ast::Arm> = field_names.iter() let value_arms: Vec<ast::Arm> = field_names.iter()
.map(|field| { .map(|field_name| {
quote_arm!(cx, __Field::$field => { quote_arm!(cx,
$field = Some(try!(visitor.visit_value())); __Field::$field_name => {
}) $field_name = Some(try!(visitor.visit_value()));
}
)
}) })
.collect(); .collect();
let extract_values: Vec<P<ast::Stmt>> = fields.iter() let extract_values: Vec<P<ast::Stmt>> = field_names.iter()
.zip(field_names.iter()) .zip(struct_def.fields.iter())
.map(|(name, field)| { .map(|(field_name, field)| {
let name_str = builder.expr().str(name); let name_str = match field.node.kind {
ast::NamedField(name, _) => builder.expr().str(name),
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
};
let missing_expr = if field::default_value(field) {
quote_expr!(cx, ::std::default::Default::default())
} else {
quote_expr!(cx, try!(visitor.missing_field($name_str)))
};
quote_stmt!(cx, quote_stmt!(cx,
let $field = match $field { let $field_name = match $field_name {
Some($field) => $field, Some($field_name) => $field_name,
None => try!(visitor.missing_field($name_str)), None => $missing_expr,
}; };
) )
}) })
@@ -429,13 +428,13 @@ fn deserialize_map(
.with_id_exprs( .with_id_exprs(
struct_def.fields.iter() struct_def.fields.iter()
.zip(field_names.iter()) .zip(field_names.iter())
.map(|(field, local)| { .map(|(field, field_name)| {
( (
match field.node.kind { match field.node.kind {
ast::NamedField(name, _) => name.clone(), ast::NamedField(name, _) => name.clone(),
ast::UnnamedField(_) => panic!("struct contains unnamed fields"), ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
}, },
builder.expr().id(local), builder.expr().id(field_name),
) )
}) })
) )
@@ -542,10 +541,6 @@ fn deserialize_variant(
) )
} }
ast::TupleVariantKind(ref args) => { ast::TupleVariantKind(ref args) => {
let fields: Vec<ast::Ident> = (0 .. args.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let expr = deserialize_tuple_variant( let expr = deserialize_tuple_variant(
cx, cx,
builder, builder,
@@ -553,16 +548,12 @@ fn deserialize_variant(
variant_ident, variant_ident,
generics, generics,
ty, ty,
fields, args.len(),
); );
quote_arm!(cx, $variant_name => { $expr }) quote_arm!(cx, $variant_name => { $expr })
} }
ast::StructVariantKind(ref struct_def) => { ast::StructVariantKind(ref struct_def) => {
let fields: Vec<_> = (0 .. struct_def.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let expr = deserialize_struct_variant( let expr = deserialize_struct_variant(
cx, cx,
builder, builder,
@@ -571,7 +562,6 @@ fn deserialize_variant(
generics, generics,
ty, ty,
struct_def, struct_def,
fields,
); );
quote_arm!(cx, $variant_name => { $expr }) quote_arm!(cx, $variant_name => { $expr })
@@ -586,15 +576,10 @@ fn deserialize_tuple_variant(
variant_ident: ast::Ident, variant_ident: ast::Ident,
generics: &ast::Generics, generics: &ast::Generics,
ty: P<ast::Ty>, ty: P<ast::Ty>,
fields: Vec<Ident>, fields: usize,
) -> P<ast::Expr> { ) -> P<ast::Expr> {
let where_clause = &generics.where_clause; let where_clause = &generics.where_clause;
// Create the field names for the fields.
let field_names: Vec<ast::Ident> = (0 .. fields.len())
.map(|i| token::str_to_ident(&format!("__field{}", i)))
.collect();
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor( let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder, builder,
generics, generics,
@@ -604,7 +589,7 @@ fn deserialize_tuple_variant(
cx, cx,
builder, builder,
builder.path().id(type_ident).id(variant_ident).build(), builder.path().id(type_ident).id(variant_ident).build(),
&field_names, fields,
); );
quote_expr!(cx, { quote_expr!(cx, {
@@ -632,7 +617,6 @@ fn deserialize_struct_variant(
generics: &ast::Generics, generics: &ast::Generics,
ty: P<ast::Ty>, ty: P<ast::Ty>,
struct_def: &ast::StructDef, struct_def: &ast::StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> { ) -> P<ast::Expr> {
let where_clause = &generics.where_clause; let where_clause = &generics.where_clause;
@@ -641,7 +625,6 @@ fn deserialize_struct_variant(
builder, builder,
struct_def, struct_def,
builder.path().id(type_ident).id(variant_ident).build(), builder.path().id(type_ident).id(variant_ident).build(),
fields,
); );
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor( let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
@@ -671,9 +654,13 @@ fn deserialize_struct_variant(
fn deserialize_field_visitor( fn deserialize_field_visitor(
cx: &ExtCtxt, cx: &ExtCtxt,
builder: &aster::AstBuilder, builder: &aster::AstBuilder,
field_names: &[ast::Ident],
struct_def: &StructDef, struct_def: &StructDef,
) -> Vec<P<ast::Item>> { ) -> Vec<P<ast::Item>> {
// 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_enum = builder.item() let field_enum = builder.item()
.attr().allow(&["non_camel_case_types"]) .attr().allow(&["non_camel_case_types"])
.enum_("__Field") .enum_("__Field")
@@ -690,8 +677,8 @@ fn deserialize_field_visitor(
// Match arms to extract a field from a string // Match arms to extract a field from a string
let field_arms: Vec<ast::Arm> = aliases.iter() let field_arms: Vec<ast::Arm> = aliases.iter()
.zip(field_names.iter()) .zip(field_names.iter())
.map(|(alias, field)| { .map(|(alias, field_name)| {
quote_arm!(cx, $alias => { Ok(__Field::$field) }) quote_arm!(cx, $alias => { Ok(__Field::$field_name) })
}) })
.collect(); .collect();
@@ -731,18 +718,10 @@ fn deserialize_struct_visitor(
builder: &aster::AstBuilder, builder: &aster::AstBuilder,
struct_def: &ast::StructDef, struct_def: &ast::StructDef,
struct_path: ast::Path, struct_path: ast::Path,
fields: Vec<Ident>,
) -> (Vec<P<ast::Item>>, P<ast::Expr>) { ) -> (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( let field_visitor = deserialize_field_visitor(
cx, cx,
builder, builder,
&field_names,
struct_def, struct_def,
); );
@@ -750,8 +729,6 @@ fn deserialize_struct_visitor(
cx, cx,
builder, builder,
struct_path, struct_path,
&field_names,
fields,
struct_def, struct_def,
); );