Implemented serializer support for serial_name attribute

This commit is contained in:
kvark 2014-09-06 21:59:48 -04:00
parent 394d0e987c
commit b3ac319530

View File

@ -15,6 +15,8 @@ use syntax::ast::{
MetaItem, MetaItem,
MetaNameValue, MetaNameValue,
Item, Item,
ItemEnum,
ItemStruct,
Expr, Expr,
MutMutable, MutMutable,
LitNil, LitNil,
@ -110,7 +112,7 @@ fn expand_deriving_serializable(cx: &mut ExtCtxt,
), ),
attributes: attrs, attributes: attrs,
combine_substructure: combine_substructure(|a, b, c| { combine_substructure: combine_substructure(|a, b, c| {
serializable_substructure(a, b, c) serializable_substructure(a, b, c, item)
}), }),
}) })
}; };
@ -118,12 +120,15 @@ fn expand_deriving_serializable(cx: &mut ExtCtxt,
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)
} }
fn serializable_substructure(cx: &ExtCtxt, span: Span, fn serializable_substructure(cx: &ExtCtxt,
substr: &Substructure) -> Gc<Expr> { span: Span,
substr: &Substructure,
item: Gc<Item>
) -> Gc<Expr> {
let serializer = substr.nonself_args[0]; let serializer = substr.nonself_args[0];
return match *substr.fields { match (&item.deref().node, substr.fields) {
Struct(ref fields) => { (&ItemStruct(ref definition, _), &Struct(ref fields)) => {
if fields.is_empty() { if fields.is_empty() {
// unit structs have no fields and need to return `Ok()` // unit structs have no fields and need to return `Ok()`
quote_expr!(cx, Ok(())) quote_expr!(cx, Ok(()))
@ -134,12 +139,15 @@ fn serializable_substructure(cx: &ExtCtxt, span: Span,
); );
let len = fields.len(); let len = fields.len();
let mut stmts: Vec<Gc<ast::Stmt>> = fields.iter() let mut stmts: Vec<Gc<ast::Stmt>> = definition.fields.iter()
.zip(fields.iter())
.enumerate() .enumerate()
.map(|(i, &FieldInfo { name, self_, span, .. })| { .map(|(i, (def, &FieldInfo { name, self_, span, .. }))| {
let name = match name { let serial_name = find_serial_name(def.node.attrs.iter());
Some(id) => token::get_ident(id), let name = match (serial_name, name) {
None => token::intern_and_get_ident(format!("_field{}", i).as_slice()), (Some(serial), _) => serial.clone(),
(None, Some(id)) => token::get_ident(id),
(None, None) => token::intern_and_get_ident(format!("_field{}", i).as_slice()),
}; };
let name = cx.expr_str(span, name); let name = cx.expr_str(span, name);
@ -159,7 +167,7 @@ fn serializable_substructure(cx: &ExtCtxt, span: Span,
} }
} }
EnumMatching(_idx, variant, ref fields) => { (&ItemEnum(ref definition, _), &EnumMatching(_idx, variant, ref fields)) => {
let type_name = cx.expr_str( let type_name = cx.expr_str(
span, span,
token::get_ident(substr.type_ident) token::get_ident(substr.type_ident)
@ -170,8 +178,10 @@ fn serializable_substructure(cx: &ExtCtxt, span: Span,
); );
let len = fields.len(); let len = fields.len();
let stmts: Vec<Gc<ast::Stmt>> = fields.iter() let stmts: Vec<Gc<ast::Stmt>> = definition.variants.iter()
.map(|&FieldInfo { self_, span, .. }| { .zip(fields.iter())
.map(|(def, &FieldInfo { self_, span, .. })| {
let _serial_name = find_serial_name(def.node.attrs.iter());
quote_stmt!( quote_stmt!(
cx, cx,
try!($serializer.serialize_enum_elt(&$self_)) try!($serializer.serialize_enum_elt(&$self_))
@ -272,25 +282,6 @@ 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,
@ -561,3 +552,22 @@ fn deserializable_static_fields(
} }
} }
} }
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
}