Switch to using MultiDecorator

This commit is contained in:
Erick Tryzelaar
2015-05-17 23:14:38 -07:00
parent 482f92af61
commit 2c24be90d2
3 changed files with 77 additions and 59 deletions
+57 -49
View File
@@ -1,6 +1,9 @@
use std::collections::HashSet; use std::collections::HashSet;
use aster;
use syntax::ast::{ use syntax::ast::{
self,
Ident, Ident,
MetaItem, MetaItem,
Item, Item,
@@ -8,25 +11,32 @@ use syntax::ast::{
StructDef, StructDef,
EnumDef, EnumDef,
}; };
use syntax::ast;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt; use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder; use syntax::ext::build::AstBuilder;
use syntax::owned_slice::OwnedSlice; use syntax::owned_slice::OwnedSlice;
use syntax::ptr::P; use syntax::ptr::P;
use aster;
use attr; use attr;
use field; use field;
pub fn expand_derive_deserialize( pub fn expand_derive_deserialize(
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
span: Span, span: Span,
_mitem: &MetaItem, meta_item: &MetaItem,
item: &Item, annotatable: Annotatable,
push: &mut FnMut(P<ast::Item>) push: &mut FnMut(Annotatable)
) { ) {
let item = match annotatable {
Annotatable::Item(item) => item,
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
return;
}
};
let builder = aster::AstBuilder::new().span(span); let builder = aster::AstBuilder::new().span(span);
let generics = match item.node { let generics = match item.node {
@@ -48,7 +58,7 @@ pub fn expand_derive_deserialize(
let body = deserialize_body( let body = deserialize_body(
cx, cx,
&builder, &builder,
item, &item,
&impl_generics, &impl_generics,
ty.clone(), ty.clone(),
); );
@@ -66,7 +76,7 @@ pub fn expand_derive_deserialize(
} }
).unwrap(); ).unwrap();
push(impl_item) push(Annotatable::Item(impl_item))
} }
fn deserialize_body( fn deserialize_body(
@@ -661,49 +671,47 @@ fn deserialize_field_visitor(
}) })
}; };
vec![ let impl_item = quote_item!(cx,
field_enum, impl ::serde::de::Deserialize for __Field {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<__Field, D::Error>
where D: ::serde::de::Deserializer,
{
use std::marker::PhantomData;
quote_item!(cx, struct __FieldVisitor<D> {
impl ::serde::de::Deserialize for __Field { phantom: PhantomData<D>
#[inline]
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<__Field, D::Error>
where D: ::serde::de::Deserializer,
{
use std::marker::PhantomData;
struct __FieldVisitor<D> {
phantom: PhantomData<D>
}
impl<__D> ::serde::de::Visitor for __FieldVisitor<__D>
where __D: ::serde::de::Deserializer
{
type Value = __Field;
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
$body
}
fn visit_bytes<E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
// TODO: would be better to generate a byte string literal match
match ::std::str::from_utf8(value) {
Ok(s) => self.visit_str(s),
_ => Err(::serde::de::Error::syntax_error()),
}
}
}
deserializer.visit(
__FieldVisitor::<D>{ phantom: PhantomData })
} }
impl<__D> ::serde::de::Visitor for __FieldVisitor<__D>
where __D: ::serde::de::Deserializer
{
type Value = __Field;
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
$body
}
fn visit_bytes<E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
// TODO: would be better to generate a byte string literal match
match ::std::str::from_utf8(value) {
Ok(s) => self.visit_str(s),
_ => Err(::serde::de::Error::syntax_error()),
}
}
}
deserializer.visit(
__FieldVisitor::<D>{ phantom: PhantomData })
} }
).unwrap(), }
] ).unwrap();
vec![field_enum, impl_item]
} }
fn deserialize_struct_visitor( fn deserialize_struct_visitor(
+2 -2
View File
@@ -14,11 +14,11 @@ mod ser;
pub fn register(reg: &mut rustc::plugin::Registry) { pub fn register(reg: &mut rustc::plugin::Registry) {
reg.register_syntax_extension( reg.register_syntax_extension(
syntax::parse::token::intern("derive_Serialize"), syntax::parse::token::intern("derive_Serialize"),
syntax::ext::base::Decorator( syntax::ext::base::MultiDecorator(
Box::new(ser::expand_derive_serialize))); Box::new(ser::expand_derive_serialize)));
reg.register_syntax_extension( reg.register_syntax_extension(
syntax::parse::token::intern("derive_Deserialize"), syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::Decorator( syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize))); Box::new(de::expand_derive_deserialize)));
} }
+18 -8
View File
@@ -1,3 +1,5 @@
use aster;
use syntax::ast::{ use syntax::ast::{
Ident, Ident,
MetaItem, MetaItem,
@@ -7,21 +9,29 @@ use syntax::ast::{
}; };
use syntax::ast; use syntax::ast;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt; use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder; use syntax::ext::build::AstBuilder;
use syntax::ptr::P; use syntax::ptr::P;
use aster;
use field::struct_field_attrs; use field::struct_field_attrs;
pub fn expand_derive_serialize( pub fn expand_derive_serialize(
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
span: Span, span: Span,
_mitem: &MetaItem, meta_item: &MetaItem,
item: &Item, annotatable: Annotatable,
push: &mut FnMut(P<ast::Item>) push: &mut FnMut(Annotatable)
) { ) {
let item = match annotatable {
Annotatable::Item(item) => item,
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
return;
}
};
let builder = aster::AstBuilder::new().span(span); let builder = aster::AstBuilder::new().span(span);
let generics = match item.node { let generics = match item.node {
@@ -43,7 +53,7 @@ pub fn expand_derive_serialize(
let body = serialize_body( let body = serialize_body(
cx, cx,
&builder, &builder,
item, &item,
&impl_generics, &impl_generics,
ty.clone(), ty.clone(),
); );
@@ -61,7 +71,7 @@ pub fn expand_derive_serialize(
} }
).unwrap(); ).unwrap();
push(impl_item) push(Annotatable::Item(impl_item))
} }
fn serialize_body( fn serialize_body(