diff --git a/serde_codegen/src/attr.rs b/serde_codegen/src/attr.rs index 6a028367..a021ef9c 100644 --- a/serde_codegen/src/attr.rs +++ b/serde_codegen/src/attr.rs @@ -9,6 +9,8 @@ use syntax::ptr::P; use aster; +use error::Error; + /// Represents field name information #[derive(Debug)] pub enum FieldNames { @@ -130,7 +132,7 @@ impl<'a> FieldAttrsBuilder<'a> { } } - pub fn field(mut self, field: &ast::StructField) -> Result, ()> { + pub fn field(mut self, field: &ast::StructField) -> Result, Error> { match field.node.kind { ast::NamedField(name, _) => { self.name = Some(self.builder.expr().str(name)); @@ -141,7 +143,7 @@ impl<'a> FieldAttrsBuilder<'a> { self.attrs(&field.node.attrs) } - pub fn attrs(mut self, attrs: &[ast::Attribute]) -> Result, ()> { + pub fn attrs(mut self, attrs: &[ast::Attribute]) -> Result, Error> { for attr in attrs { self = try!(self.attr(attr)); } @@ -149,7 +151,7 @@ impl<'a> FieldAttrsBuilder<'a> { Ok(self) } - pub fn attr(mut self, attr: &ast::Attribute) -> Result, ()> { + pub fn attr(mut self, attr: &ast::Attribute) -> Result, Error> { match attr.node.value.node { ast::MetaList(ref name, ref items) if name == &"serde" => { attr::mark_used(&attr); @@ -165,7 +167,8 @@ impl<'a> FieldAttrsBuilder<'a> { } } - pub fn meta_item(mut self, meta_item: &P) -> Result, ()> { + pub fn meta_item(mut self, + meta_item: &P) -> Result, Error> { match meta_item.node { ast::MetaNameValue(ref name, ref lit) if name == &"rename" => { let expr = self.builder.expr().build_lit(P(lit.clone())); @@ -204,7 +207,7 @@ impl<'a> FieldAttrsBuilder<'a> { meta_item.span, &format!("unknown serde field attribute `{}`", meta_item_to_string(meta_item))); - Err(()) + Err(Error) } } } @@ -285,7 +288,7 @@ impl<'a> ContainerAttrsBuilder<'a> { } } - pub fn attrs(mut self, attrs: &[ast::Attribute]) -> Result { + pub fn attrs(mut self, attrs: &[ast::Attribute]) -> Result { for attr in attrs { self = try!(self.attr(attr)); } @@ -293,7 +296,7 @@ impl<'a> ContainerAttrsBuilder<'a> { Ok(self) } - pub fn attr(mut self, attr: &ast::Attribute) -> Result { + pub fn attr(mut self, attr: &ast::Attribute) -> Result { match attr.node.value.node { ast::MetaList(ref name, ref items) if name == &"serde" => { attr::mark_used(&attr); @@ -309,7 +312,7 @@ impl<'a> ContainerAttrsBuilder<'a> { } } - pub fn meta_item(self, meta_item: &P) -> Result { + pub fn meta_item(self, meta_item: &P) -> Result { match meta_item.node { ast::MetaWord(ref name) if name == &"deny_unknown_fields" => { Ok(self.deny_unknown_fields()) @@ -319,7 +322,7 @@ impl<'a> ContainerAttrsBuilder<'a> { meta_item.span, &format!("unknown serde container attribute `{}`", meta_item_to_string(meta_item))); - Err(()) + Err(Error) } } } @@ -335,3 +338,28 @@ impl<'a> ContainerAttrsBuilder<'a> { } } } + +/// Extract out the `#[serde(...)]` attributes from an item. +pub fn get_container_attrs(cx: &ExtCtxt, + container: &ast::Item, + ) -> Result { + let builder = ContainerAttrsBuilder::new(cx); + let builder = try!(builder.attrs(container.attrs())); + Ok(builder.build()) +} + +/// Extract out the `#[serde(...)]` attributes from a struct field. +pub fn get_struct_field_attrs(cx: &ExtCtxt, + builder: &aster::AstBuilder, + fields: &[ast::StructField] + ) -> Result, Error> { + let mut attrs = vec![]; + for field in fields { + let builder = FieldAttrsBuilder::new(cx, builder); + let builder = try!(builder.field(field)); + let attr = builder.build(); + attrs.push(attr); + } + + Ok(attrs) +} diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 107f8872..5a893e5f 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -15,7 +15,8 @@ use syntax::ext::build::AstBuilder; use syntax::ptr::P; use attr::{self, ContainerAttrs}; -use field; + +use error::Error; pub fn expand_derive_deserialize( cx: &mut ExtCtxt, @@ -59,7 +60,7 @@ pub fn expand_derive_deserialize( let body = match deserialize_body(cx, &builder, &item, &impl_generics, ty.clone()) { Ok(body) => body, - Err(()) => { + Err(Error) => { // An error occured, but it should have been reported already. return; } @@ -86,8 +87,8 @@ fn deserialize_body( item: &Item, impl_generics: &ast::Generics, ty: P, -) -> Result, ()> { - let container_attrs = try!(field::container_attrs(cx, item)); +) -> Result, Error> { + let container_attrs = try!(attr::get_container_attrs(cx, item)); match item.node { ast::ItemStruct(ref variant_data, _) => { @@ -129,7 +130,7 @@ fn deserialize_item_struct( span: Span, variant_data: &ast::VariantData, container_attrs: &ContainerAttrs, -) -> Result, ()> { +) -> Result, Error> { match *variant_data { ast::VariantData::Unit(_) => { deserialize_unit_struct( @@ -186,7 +187,7 @@ fn deserialize_visitor( trait_generics: &ast::Generics, forward_ty_params: Vec, forward_tys: Vec> -) -> Result<(P, P, P, ast::Generics), ()> { +) -> Result<(P, P, P, ast::Generics), Error> { if trait_generics.ty_params.is_empty() && forward_tys.is_empty() { Ok(( builder.item().tuple_struct("__Visitor").build(), @@ -265,7 +266,7 @@ fn deserialize_unit_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, type_ident: Ident, -) -> Result, ()> { +) -> Result, Error> { let type_name = builder.expr().str(type_ident); Ok(quote_expr!(cx, { @@ -300,7 +301,7 @@ fn deserialize_newtype_struct( type_ident: Ident, impl_generics: &ast::Generics, ty: P, -) -> Result, ()> { +) -> Result, Error> { let where_clause = &impl_generics.where_clause; let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor( @@ -352,7 +353,7 @@ fn deserialize_tuple_struct( impl_generics: &ast::Generics, ty: P, fields: usize, -) -> Result, ()> { +) -> Result, Error> { let where_clause = &impl_generics.where_clause; let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor( @@ -428,7 +429,7 @@ fn deserialize_struct_as_seq( builder: &aster::AstBuilder, struct_path: ast::Path, fields: &[ast::StructField], -) -> Result, ()> { +) -> Result, Error> { let let_values: Vec> = (0 .. fields.len()) .map(|i| { let name = builder.id(format!("__field{}", i)); @@ -478,7 +479,7 @@ fn deserialize_struct( ty: P, fields: &[ast::StructField], container_attrs: &ContainerAttrs, -) -> Result, ()> { +) -> Result, Error> { let where_clause = &impl_generics.where_clause; let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor( @@ -544,7 +545,7 @@ fn deserialize_item_enum( ty: P, enum_def: &EnumDef, container_attrs: &ContainerAttrs -) -> Result, ()> { +) -> Result, Error> { let where_clause = &impl_generics.where_clause; let type_name = builder.expr().str(type_ident); @@ -642,7 +643,7 @@ fn deserialize_variant( ty: P, variant: &ast::Variant, container_attrs: &ContainerAttrs, -) -> Result, ()> { +) -> Result, Error> { let variant_ident = variant.node.name; match variant.node.data { @@ -692,7 +693,7 @@ fn deserialize_tuple_variant( generics: &ast::Generics, ty: P, fields: usize, -) -> Result, ()> { +) -> Result, Error> { let where_clause = &generics.where_clause; let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor( @@ -735,7 +736,7 @@ fn deserialize_struct_variant( ty: P, fields: &[ast::StructField], container_attrs: &ContainerAttrs, -) -> Result, ()> { +) -> Result, Error> { let where_clause = &generics.where_clause; let type_path = builder.path() @@ -963,11 +964,11 @@ fn deserialize_struct_visitor( struct_path: ast::Path, fields: &[ast::StructField], container_attrs: &ContainerAttrs, -) -> Result<(Vec>, P, P), ()> { +) -> Result<(Vec>, P, P), Error> { let field_visitor = deserialize_field_visitor( cx, builder, - try!(field::struct_field_attrs(cx, builder, fields)), + try!(attr::get_struct_field_attrs(cx, builder, fields)), container_attrs ); @@ -1006,7 +1007,7 @@ fn deserialize_map( struct_path: ast::Path, fields: &[ast::StructField], container_attrs: &ContainerAttrs, -) -> Result, ()> { +) -> Result, Error> { // Create the field names for the fields. let field_names: Vec = (0 .. fields.len()) .map(|i| builder.id(format!("__field{}", i))) @@ -1039,7 +1040,7 @@ fn deserialize_map( .chain(ignored_arm.into_iter()) .collect(); - let field_attrs = try!(field::struct_field_attrs(cx, builder, fields)); + let field_attrs = try!(attr::get_struct_field_attrs(cx, builder, fields)); let extract_values: Vec> = field_names.iter() .zip(field_attrs.iter()) diff --git a/serde_codegen/src/error.rs b/serde_codegen/src/error.rs new file mode 100644 index 00000000..8a76cf30 --- /dev/null +++ b/serde_codegen/src/error.rs @@ -0,0 +1,2 @@ +/// Error returned if failed to parse attribute. +pub struct Error; diff --git a/serde_codegen/src/field.rs b/serde_codegen/src/field.rs deleted file mode 100644 index 43fe4f90..00000000 --- a/serde_codegen/src/field.rs +++ /dev/null @@ -1,30 +0,0 @@ -use syntax::ast; -use syntax::ext::base::ExtCtxt; - -use aster; -use attr; - -pub fn struct_field_attrs( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - fields: &[ast::StructField], -) -> Result, ()> { - let mut attrs = vec![]; - for field in fields { - let builder = attr::FieldAttrsBuilder::new(cx, builder); - let builder = try!(builder.field(field)); - let attr = builder.build(); - attrs.push(attr); - } - - Ok(attrs) -} - -pub fn container_attrs( - cx: &ExtCtxt, - container: &ast::Item, -) -> Result { - let builder = attr::ContainerAttrsBuilder::new(cx); - let builder = try!(builder.attrs(container.attrs())); - Ok(builder.build()) -} diff --git a/serde_codegen/src/lib.rs.in b/serde_codegen/src/lib.rs.in index 18f155ec..9c7c34fb 100644 --- a/serde_codegen/src/lib.rs.in +++ b/serde_codegen/src/lib.rs.in @@ -1,4 +1,4 @@ mod attr; mod de; -mod field; +mod error; mod ser; diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index f8c63649..7a61c6a2 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -11,7 +11,8 @@ use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; -use field; +use attr; +use error::Error; pub fn expand_derive_serialize( cx: &mut ExtCtxt, @@ -55,7 +56,7 @@ pub fn expand_derive_serialize( let body = match serialize_body(cx, &builder, &item, &impl_generics, ty.clone()) { Ok(body) => body, - Err(()) => { + Err(Error) => { // An error occured, but it should have been reported already. return; } @@ -82,10 +83,10 @@ fn serialize_body( item: &Item, impl_generics: &ast::Generics, ty: P, -) -> Result, ()> { +) -> Result, Error> { // Note: While we don't have any container attributes, we still want to try to // parse them so we can report a proper error if we get passed an unknown attribute. - let _ = try!(field::container_attrs(cx, item)); + let _ = try!(attr::get_container_attrs(cx, item)); match item.node { ast::ItemStruct(ref variant_data, _) => { @@ -124,7 +125,7 @@ fn serialize_item_struct( ty: P, span: Span, variant_data: &ast::VariantData, -) -> Result, ()> { +) -> Result, Error> { match *variant_data { ast::VariantData::Unit(_) => { serialize_unit_struct( @@ -175,7 +176,7 @@ fn serialize_unit_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, type_ident: Ident -) -> Result, ()> { +) -> Result, Error> { let type_name = builder.expr().str(type_ident); Ok(quote_expr!(cx, @@ -187,7 +188,7 @@ fn serialize_newtype_struct( cx: &ExtCtxt, builder: &aster::AstBuilder, type_ident: Ident -) -> Result, ()> { +) -> Result, Error> { let type_name = builder.expr().str(type_ident); Ok(quote_expr!(cx, @@ -202,7 +203,7 @@ fn serialize_tuple_struct( impl_generics: &ast::Generics, ty: P, fields: usize, -) -> Result, ()> { +) -> Result, Error> { let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor( cx, builder, @@ -235,7 +236,7 @@ fn serialize_struct( impl_generics: &ast::Generics, ty: P, fields: &[ast::StructField], -) -> Result, ()> { +) -> Result, Error> { let value_exprs = fields.iter().map(|field| { let name = field.node.ident().expect("struct has unnamed field"); quote_expr!(cx, &self.value.$name) @@ -274,7 +275,7 @@ fn serialize_item_enum( impl_generics: &ast::Generics, ty: P, enum_def: &ast::EnumDef, -) -> Result, ()> { +) -> Result, Error> { let mut arms = vec![]; for (variant_index, variant) in enum_def.variants.iter().enumerate() { @@ -306,7 +307,7 @@ fn serialize_variant( ty: P, variant: &ast::Variant, variant_index: usize, -) -> Result { +) -> Result { let type_name = builder.expr().str(type_ident); let variant_ident = variant.node.name; let variant_name = builder.expr().str(variant_ident); @@ -479,7 +480,7 @@ fn serialize_struct_variant( structure_ty: P, fields: &[ast::StructField], field_names: Vec, -) -> Result, ()> { +) -> Result, Error> { let value_ty = builder.ty().tuple() .with_tys( fields.iter().map(|field| { @@ -599,12 +600,12 @@ fn serialize_struct_visitor( fields: &[ast::StructField], generics: &ast::Generics, value_exprs: I, -) -> Result<(P, P), ()> +) -> Result<(P, P), Error> where I: Iterator>, { let value_exprs = value_exprs.collect::>(); - let field_attrs = try!(field::struct_field_attrs(cx, builder, fields)); + let field_attrs = try!(attr::get_struct_field_attrs(cx, builder, fields)); let arms: Vec = field_attrs.iter() .zip(value_exprs.iter())