Implemented serial_name attribute

This commit is contained in:
kvark 2014-09-05 23:22:01 -04:00
parent bc92cb884c
commit 394d0e987c

View File

@ -10,14 +10,21 @@ extern crate rustc;
use std::gc::Gc; use std::gc::Gc;
use syntax::ast::{ use syntax::ast::{
Attribute,
Ident, Ident,
MetaItem, MetaItem,
MetaNameValue,
Item, Item,
Expr, Expr,
MutMutable, MutMutable,
LitNil, LitNil,
LitStr,
P,
StructField,
Variant,
}; };
use syntax::ast; use syntax::ast;
use syntax::attr;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, ItemDecorator}; use syntax::ext::base::{ExtCtxt, ItemDecorator};
use syntax::ext::build::AstBuilder; use syntax::ext::build::AstBuilder;
@ -241,20 +248,22 @@ fn deserializable_substructure(cx: &mut ExtCtxt, span: Span,
let token = substr.nonself_args[1]; let token = substr.nonself_args[1];
match *substr.fields { match *substr.fields {
StaticStruct(_, ref fields) => { StaticStruct(ref definition, ref fields) => {
deserialize_struct( deserialize_struct(
cx, cx,
span, span,
substr.type_ident, substr.type_ident,
definition.fields.as_slice(),
fields, fields,
deserializer, deserializer,
token) token)
} }
StaticEnum(_, ref fields) => { StaticEnum(ref definition, ref fields) => {
deserialize_enum( deserialize_enum(
cx, cx,
span, span,
substr.type_ident, substr.type_ident,
definition.variants.as_slice(),
fields.as_slice(), fields.as_slice(),
deserializer, deserializer,
token) token)
@ -263,18 +272,43 @@ fn deserializable_substructure(cx: &mut ExtCtxt, span: Span,
} }
} }
fn find_serial_name<'a, I: Iterator<&'a Attribute>>(mut iterator: I)
-> Option<token::InternedString> {
for at in iterator {
match at.node.value.node {
MetaNameValue(ref at_name, ref value) => {
match (at_name.get(), &value.node) {
("serial_name", &LitStr(ref string, _)) => {
attr::mark_used(at);
return Some(string.clone());
},
_ => ()
}
},
_ => ()
}
}
None
}
fn deserialize_struct( fn deserialize_struct(
cx: &ExtCtxt, cx: &ExtCtxt,
span: Span, span: Span,
type_ident: Ident, type_ident: Ident,
definitions: &[StructField],
fields: &StaticFields, fields: &StaticFields,
deserializer: Gc<ast::Expr>, deserializer: Gc<ast::Expr>,
token: Gc<ast::Expr> token: Gc<ast::Expr>
) -> Gc<ast::Expr> { ) -> Gc<ast::Expr> {
let serial_names = definitions.iter().map(|def|
find_serial_name(def.node.attrs.iter())
).collect();
let struct_block = deserialize_struct_from_struct( let struct_block = deserialize_struct_from_struct(
cx, cx,
span, span,
type_ident, type_ident,
serial_names,
fields, fields,
deserializer deserializer
); );
@ -307,6 +341,7 @@ fn deserialize_struct_from_struct(
cx: &ExtCtxt, cx: &ExtCtxt,
span: Span, span: Span,
type_ident: Ident, type_ident: Ident,
serial_names: Vec<Option<token::InternedString>>,
fields: &StaticFields, fields: &StaticFields,
deserializer: Gc<ast::Expr> deserializer: Gc<ast::Expr>
) -> Gc<ast::Expr> { ) -> Gc<ast::Expr> {
@ -316,6 +351,7 @@ fn deserialize_struct_from_struct(
cx, cx,
span, span,
type_ident, type_ident,
serial_names.as_slice(),
fields, fields,
|cx, span, name| { |cx, span, name| {
let name = cx.expr_str(span, name); let name = cx.expr_str(span, name);
@ -428,12 +464,17 @@ fn deserialize_enum(
cx: &ExtCtxt, cx: &ExtCtxt,
span: Span, span: Span,
type_ident: Ident, type_ident: Ident,
definitions: &[P<Variant>],
fields: &[(Ident, Span, StaticFields)], fields: &[(Ident, Span, StaticFields)],
deserializer: Gc<ast::Expr>, deserializer: Gc<ast::Expr>,
token: Gc<ast::Expr> token: Gc<ast::Expr>
) -> Gc<ast::Expr> { ) -> Gc<ast::Expr> {
let type_name = cx.expr_str(span, token::get_ident(type_ident)); let type_name = cx.expr_str(span, token::get_ident(type_ident));
let serial_names = definitions.iter().map(|def|
find_serial_name(def.node.attrs.iter())
).collect::<Vec<Option<token::InternedString>>>();
let variants = fields.iter() let variants = fields.iter()
.map(|&(name, span, _)| { .map(|&(name, span, _)| {
cx.expr_str(span, token::get_ident(name)) cx.expr_str(span, token::get_ident(name))
@ -449,6 +490,7 @@ fn deserialize_enum(
cx, cx,
span, span,
name, name,
serial_names.as_slice(),
parts, parts,
|cx, span, _| { |cx, span, _| {
quote_expr!(cx, try!($deserializer.expect_enum_elt())) quote_expr!(cx, try!($deserializer.expect_enum_elt()))
@ -480,6 +522,7 @@ fn deserializable_static_fields(
cx: &ExtCtxt, cx: &ExtCtxt,
span: Span, span: Span,
outer_pat_ident: Ident, outer_pat_ident: Ident,
serial_names: &[Option<token::InternedString>],
fields: &StaticFields, fields: &StaticFields,
getarg: |&ExtCtxt, Span, token::InternedString| -> Gc<Expr> getarg: |&ExtCtxt, Span, token::InternedString| -> Gc<Expr>
) -> Gc<Expr> { ) -> Gc<Expr> {
@ -501,11 +544,15 @@ fn deserializable_static_fields(
} }
Named(ref fields) => { Named(ref fields) => {
// use the field's span to get nicer error messages. // use the field's span to get nicer error messages.
let fields = fields.iter().map(|&(name, span)| { let fields = serial_names.iter()
.zip(fields.iter()).map(|(serial_name, &(name, span))| {
let effective_name = serial_name.clone().unwrap_or(
token::get_ident(name)
);
let arg = getarg( let arg = getarg(
cx, cx,
span, span,
token::get_ident(name) effective_name
); );
cx.field_imm(span, name, arg) cx.field_imm(span, name, arg)
}).collect(); }).collect();