diff --git a/serde_codegen/src/attr.rs b/serde_codegen/src/attr.rs index 7c69cdf1..b440af7e 100644 --- a/serde_codegen/src/attr.rs +++ b/serde_codegen/src/attr.rs @@ -166,6 +166,7 @@ pub struct FieldAttrs { serialize_name: Option, deserialize_name: Option, skip_serializing_field: bool, + skip_serializing_field_if: Option>, skip_serializing_field_if_empty: bool, skip_serializing_field_if_none: bool, default_expr_if_missing: Option>, @@ -174,6 +175,7 @@ pub struct FieldAttrs { impl FieldAttrs { /// Extract out the `#[serde(...)]` attributes from a struct field. pub fn from_field(cx: &ExtCtxt, + container_ty: &P, generics: &ast::Generics, field: &ast::StructField) -> Result { let builder = AstBuilder::new(); @@ -188,6 +190,7 @@ impl FieldAttrs { serialize_name: None, deserialize_name: None, skip_serializing_field: false, + skip_serializing_field_if: None, skip_serializing_field_if_empty: false, skip_serializing_field_if_none: false, default_expr_if_missing: None, @@ -232,6 +235,18 @@ impl FieldAttrs { field_attrs.skip_serializing_field = true; } + // Parse `#[serde(skip_serializing_if="...")]` + ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"skip_serializing_if" => { + let expr = wrap_skip_serializing( + cx, + container_ty, + generics, + try!(parse_lit_into_expr(cx, name, lit)), + ); + + field_attrs.skip_serializing_field_if = Some(expr); + } + // Parse `#[serde(skip_serializing_if_none)]` ast::MetaItemKind::Word(ref name) if name == &"skip_serializing_if_none" => { field_attrs.skip_serializing_field_if_none = true; @@ -298,6 +313,10 @@ impl FieldAttrs { self.skip_serializing_field } + pub fn skip_serializing_field_if(&self) -> Option<&P> { + self.skip_serializing_field_if.as_ref() + } + pub fn skip_serializing_field_if_empty(&self) -> bool { self.skip_serializing_field_if_empty } @@ -307,12 +326,14 @@ impl FieldAttrs { } } + /// Extract out the `#[serde(...)]` attributes from a struct field. pub fn get_struct_field_attrs(cx: &ExtCtxt, + container_ty: &P, generics: &ast::Generics, fields: &[ast::StructField]) -> Result, Error> { fields.iter() - .map(|field| FieldAttrs::from_field(cx, generics, field)) + .map(|field| FieldAttrs::from_field(cx, container_ty, generics, field)) .collect() } @@ -401,3 +422,26 @@ fn wrap_default(cx: &ExtCtxt, $fn_path() }) } + +/// This function wraps the expression in `#[serde(skip_serializing_if="...")]` in a trait to +/// prevent it from accessing the internal `Serialize` state. +fn wrap_skip_serializing(cx: &ExtCtxt, + container_ty: &P, + generics: &ast::Generics, + expr: P) -> P { + let where_clause = &generics.where_clause; + + quote_expr!(cx, { + trait __SerdeShouldSkipSerializing { + fn __serde_should_skip_serializing(&self) -> bool; + } + + impl $generics __SerdeShouldSkipSerializing for $container_ty $where_clause { + fn __serde_should_skip_serializing(&self) -> bool { + $expr + } + } + + self.value.__serde_should_skip_serializing() + }) +} diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 458913e0..e95fe2dc 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -503,6 +503,7 @@ fn deserialize_struct( cx, builder, type_path.clone(), + &ty, impl_generics, fields, container_attrs @@ -757,6 +758,7 @@ fn deserialize_struct_variant( cx, builder, type_path, + &ty, generics, fields, container_attrs, @@ -920,13 +922,19 @@ fn deserialize_struct_visitor( cx: &ExtCtxt, builder: &aster::AstBuilder, struct_path: ast::Path, + container_ty: &P, generics: &ast::Generics, fields: &[ast::StructField], container_attrs: &attr::ContainerAttrs, ) -> Result<(Vec>, ast::Stmt, P), Error> { let field_exprs = fields.iter() .map(|field| { - let field_attrs = try!(attr::FieldAttrs::from_field(cx, generics, field)); + let field_attrs = try!( + attr::FieldAttrs::from_field(cx, + container_ty, + generics, + field) + ); Ok(field_attrs.deserialize_name_expr()) }) .collect(); @@ -942,6 +950,7 @@ fn deserialize_struct_visitor( cx, builder, struct_path, + container_ty, generics, fields, container_attrs, @@ -972,6 +981,7 @@ fn deserialize_map( cx: &ExtCtxt, builder: &aster::AstBuilder, struct_path: ast::Path, + container_ty: &P, generics: &ast::Generics, fields: &[ast::StructField], container_attrs: &attr::ContainerAttrs, @@ -1011,7 +1021,12 @@ fn deserialize_map( let extract_values = fields.iter() .zip(field_names.iter()) .map(|(field, field_name)| { - let field_attr = try!(attr::FieldAttrs::from_field(cx, generics, field)); + let field_attr = try!( + attr::FieldAttrs::from_field(cx, + container_ty, + generics, + field) + ); let missing_expr = field_attr.expr_is_missing(); Ok(quote_stmt!(cx, diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 7aef3de1..a604d298 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -33,14 +33,30 @@ pub fn expand_derive_serialize( let builder = aster::AstBuilder::new().span(span); + let impl_item = match serialize_item(cx, &builder, &item) { + Ok(item) => item, + Err(Error) => { + // An error occured, but it should have been reported already. + return; + } + }; + + push(Annotatable::Item(impl_item)) +} + +fn serialize_item( + cx: &ExtCtxt, + builder: &aster::AstBuilder, + item: &Item, +) -> Result, Error> { let generics = match item.node { ast::ItemKind::Struct(_, ref generics) => generics, ast::ItemKind::Enum(_, ref generics) => generics, _ => { cx.span_err( - meta_item.span, + item.span, "`#[derive(Serialize)]` may only be applied to structs and enums"); - return; + return Err(Error); } }; @@ -54,17 +70,15 @@ pub fn expand_derive_serialize( .segment(item.ident).with_generics(impl_generics.clone()).build() .build(); - let body = match serialize_body(cx, &builder, &item, &impl_generics, ty.clone()) { - Ok(body) => body, - Err(Error) => { - // An error occured, but it should have been reported already. - return; - } - }; + let body = try!(serialize_body(cx, + &builder, + &item, + &impl_generics, + ty.clone())); let where_clause = &impl_generics.where_clause; - let impl_item = quote_item!(cx, + Ok(quote_item!(cx, impl $impl_generics ::serde::ser::Serialize for $ty $where_clause { fn serialize<__S>(&self, serializer: &mut __S) -> ::std::result::Result<(), __S::Error> where __S: ::serde::ser::Serializer, @@ -72,9 +86,7 @@ pub fn expand_derive_serialize( $body } } - ).unwrap(); - - push(Annotatable::Item(impl_item)) + ).unwrap()) } fn serialize_body( @@ -207,6 +219,7 @@ fn serialize_tuple_struct( .ref_() .lifetime("'__a") .build_ty(ty.clone()), + builder.id("serialize_tuple_struct_elt"), fields, impl_generics, ); @@ -232,11 +245,6 @@ fn serialize_struct( fields: &[ast::StructField], container_attrs: &attr::ContainerAttrs, ) -> 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) - }); - let (visitor_struct, visitor_impl) = try!(serialize_struct_visitor( cx, builder, @@ -245,9 +253,9 @@ fn serialize_struct( .ref_() .lifetime("'__a") .build_ty(ty.clone()), + builder.id("serialize_struct_elt"), fields, impl_generics, - value_exprs, )); let type_name = container_attrs.serialize_name_expr(); @@ -272,22 +280,23 @@ fn serialize_item_enum( enum_def: &ast::EnumDef, container_attrs: &attr::ContainerAttrs, ) -> Result, Error> { - let mut arms = vec![]; - - for (variant_index, variant) in enum_def.variants.iter().enumerate() { - let arm = try!(serialize_variant( - cx, - builder, - type_ident, - impl_generics, - ty.clone(), - variant, - variant_index, - container_attrs, - )); - - arms.push(arm); - } + let arms: Vec<_> = try!( + enum_def.variants.iter() + .enumerate() + .map(|(variant_index, variant)| { + serialize_variant( + cx, + builder, + type_ident, + impl_generics, + ty.clone(), + variant, + variant_index, + container_attrs, + ) + }) + .collect() + ); Ok(quote_expr!(cx, match *self { @@ -404,13 +413,13 @@ fn serialize_variant( let expr = try!(serialize_struct_variant( cx, builder, - type_name, variant_index, variant_name, generics, ty, fields, field_names, + container_attrs, )); Ok(quote_arm!(cx, @@ -447,6 +456,7 @@ fn serialize_tuple_variant( builder, structure_ty.clone(), variant_ty, + builder.id("serialize_tuple_variant_elt"), fields.len(), generics, ); @@ -473,55 +483,88 @@ fn serialize_tuple_variant( fn serialize_struct_variant( cx: &ExtCtxt, builder: &aster::AstBuilder, - type_name: P, variant_index: usize, variant_name: P, generics: &ast::Generics, - structure_ty: P, + ty: P, fields: &[ast::StructField], field_names: Vec, + container_attrs: &attr::ContainerAttrs, ) -> Result, Error> { - let value_ty = builder.ty().tuple() - .with_tys( + let variant_generics = builder.generics() + .with(generics.clone()) + .add_lifetime_bound("'__serde_variant") + .lifetime_name("'__serde_variant") + .build(); + + let variant_struct = builder.item().struct_("__VariantStruct") + .with_generics(variant_generics.clone()) + .with_fields( fields.iter().map(|field| { - builder.ty() + builder.struct_field(field.node.ident().expect("struct has unnamed fields")) + .with_attrs(field.node.attrs.iter().cloned()) + .ty() .ref_() - .lifetime("'__a") + .lifetime("'__serde_variant") .build_ty(field.node.ty.clone()) }) ) + .field("__serde_container_ty") + .ty().phantom_data().build(ty.clone()) .build(); - let value_expr = builder.expr().tuple() - .with_exprs( - field_names.iter().map(|field| { - builder.expr().id(field) - }) + let variant_expr = builder.expr().struct_id("__VariantStruct") + .with_id_exprs( + fields.iter() + .zip(field_names.iter()) + .map(|(field, field_name)| { + ( + field.node.ident().expect("struct has unnamed fields"), + builder.expr().id(field_name), + ) + }) ) + .field("__serde_container_ty").path() + .global() + .id("std").id("marker") + .segment("PhantomData") + .with_ty(ty.clone()) + .build() + .build() + .build(); + + let variant_ty = builder.ty().path() + .segment("__VariantStruct") + .with_generics(variant_generics.clone()) + .build() .build(); let (visitor_struct, visitor_impl) = try!(serialize_struct_visitor( cx, builder, - structure_ty.clone(), - value_ty, + variant_ty.clone(), + variant_ty.clone(), + builder.id("serialize_struct_variant_elt"), fields, - generics, - (0 .. field_names.len()).map(|i| { - builder.expr() - .tup_field(i) - .field("value").self_() - }) + &variant_generics, )); + let container_name = container_attrs.serialize_name_expr(); + Ok(quote_expr!(cx, { + $variant_struct $visitor_struct $visitor_impl - serializer.serialize_struct_variant($type_name, $variant_index, $variant_name, Visitor { - value: $value_expr, - state: 0, - _structure_ty: ::std::marker::PhantomData::<&$structure_ty>, - }) + serializer.serialize_struct_variant( + $container_name, + $variant_index, + $variant_name, + Visitor { + value: $variant_expr, + state: 0, + _structure_ty: ::std::marker::PhantomData, + }, + ) })) } @@ -530,20 +573,21 @@ fn serialize_tuple_struct_visitor( builder: &aster::AstBuilder, structure_ty: P, variant_ty: P, + serializer_method: ast::Ident, fields: usize, generics: &ast::Generics ) -> (P, P) { let arms: Vec = (0 .. fields) .map(|i| { - let expr = builder.expr() - .tup_field(i) - .field("value").self_(); + let expr = builder.expr().method_call(serializer_method) + .id("serializer") + .arg().ref_().tup_field(i).field("value").self_() + .build(); quote_arm!(cx, $i => { self.state += 1; - let v = try!(serializer.serialize_tuple_struct_elt(&$expr)); - Ok(Some(v)) + Ok(Some(try!($expr))) } ) }) @@ -592,51 +636,51 @@ fn serialize_tuple_struct_visitor( ) } -fn serialize_struct_visitor( +fn serialize_struct_visitor( cx: &ExtCtxt, builder: &aster::AstBuilder, structure_ty: P, variant_ty: P, + serializer_method: ast::Ident, fields: &[ast::StructField], generics: &ast::Generics, - value_exprs: I, -) -> Result<(P, P), Error> - where I: Iterator>, -{ - let value_exprs = value_exprs.collect::>(); +) -> Result<(P, P), Error> { + let field_attrs = try!( + attr::get_struct_field_attrs(cx, &structure_ty, generics, fields) + ); - let field_attrs = try!(attr::get_struct_field_attrs(cx, generics, fields)); - - let arms: Vec = field_attrs.iter() - .zip(value_exprs.iter()) - .filter(|&(ref field, _)| !field.skip_serializing_field()) + let arms: Vec = fields.iter().zip(field_attrs.iter()) + .filter(|&(_, ref field_attr)| !field_attr.skip_serializing_field()) .enumerate() - .map(|(i, (ref field, value_expr))| { - let key_expr = field.serialize_name_expr(); + .map(|(i, (ref field, ref field_attr))| { + let name = field.node.ident().expect("struct has unnamed field"); - let stmt = if field.skip_serializing_field_if_empty() { - quote_stmt!(cx, if ($value_expr).is_empty() { continue; }) - } else if field.skip_serializing_field_if_none() { - quote_stmt!(cx, if ($value_expr).is_none() { continue; }) - } else { - quote_stmt!(cx, {}) + let key_expr = field_attr.serialize_name_expr(); + + let stmt = match field_attr.skip_serializing_field_if() { + Some(expr) => { + Some(quote_stmt!(cx, if $expr { continue; })) + } + None => { + if field_attr.skip_serializing_field_if_empty() { + Some(quote_stmt!(cx, if self.value.$name.is_empty() { continue; })) + } else if field_attr.skip_serializing_field_if_none() { + Some(quote_stmt!(cx, if self.value.$name.is_none() { continue; })) + } else { + None + } + } }; + let expr = quote_expr!(cx, + serializer.$serializer_method($key_expr, &self.value.$name) + ); + quote_arm!(cx, $i => { self.state += 1; $stmt - - return Ok( - Some( - try!( - serializer.serialize_struct_elt( - $key_expr, - $value_expr, - ) - ) - ) - ); + return Ok(Some(try!($expr))); } ) }) @@ -653,17 +697,27 @@ fn serialize_struct_visitor( .strip_bounds() .build(); - let len = field_attrs.iter() - .zip(value_exprs.iter()) - .map(|(field, value_expr)| { - if field.skip_serializing_field() { + let len = fields.iter().zip(field_attrs.iter()) + .map(|(field, field_attr)| { + if field_attr.skip_serializing_field() { quote_expr!(cx, 0) - } else if field.skip_serializing_field_if_empty() { - quote_expr!(cx, if ($value_expr).is_empty() { 0 } else { 1 }) - } else if field.skip_serializing_field_if_none() { - quote_expr!(cx, if ($value_expr).is_none() { 0 } else { 1 }) } else { - quote_expr!(cx, 1) + match field_attr.skip_serializing_field_if() { + Some(expr) => { + quote_expr!(cx, if $expr { 0 } else { 1 }) + } + None => { + let name = field.node.ident().expect("struct has unnamed field"); + + if field_attr.skip_serializing_field_if_empty() { + quote_expr!(cx, if self.value.$name.is_empty() { 0 } else { 1 }) + } else if field_attr.skip_serializing_field_if_none() { + quote_expr!(cx, if self.value.$name.is_none() { 0 } else { 1 }) + } else { + quote_expr!(cx, 1) + } + } + } } }) .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); diff --git a/serde_tests/tests/test_annotations.rs b/serde_tests/tests/test_annotations.rs index 7f525746..831c32cd 100644 --- a/serde_tests/tests/test_annotations.rs +++ b/serde_tests/tests/test_annotations.rs @@ -9,10 +9,14 @@ use token::{ trait Trait { fn my_default() -> Self; + + fn should_skip(&self) -> bool; } impl Trait for i32 { fn my_default() -> Self { 123 } + + fn should_skip(&self) -> bool { *self == 123 } } #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -31,19 +35,19 @@ fn test_default_struct() { vec![ Token::StructStart("DefaultStruct", Some(3)), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("a2"), Token::I32(2), - Token::MapSep, + Token::StructSep, Token::Str("a3"), Token::I32(3), - Token::MapEnd, + Token::StructEnd, ] ); @@ -52,11 +56,11 @@ fn test_default_struct() { vec![ Token::StructStart("DefaultStruct", Some(1)), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapEnd, + Token::StructEnd, ] ); } @@ -79,19 +83,19 @@ fn test_default_enum() { vec![ Token::EnumMapStart("DefaultEnum", "Struct", Some(3)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::EnumMapSep, Token::Str("a2"), Token::I32(2), - Token::MapSep, + Token::EnumMapSep, Token::Str("a3"), Token::I32(3), - Token::MapEnd, + Token::EnumMapEnd, ] ); @@ -100,11 +104,11 @@ fn test_default_enum() { vec![ Token::EnumMapStart("DefaultEnum", "Struct", Some(3)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a1"), Token::I32(1), - Token::MapEnd, + Token::EnumMapEnd, ] ); } @@ -123,34 +127,34 @@ fn test_ignore_unknown() { vec![ Token::StructStart("DefaultStruct", Some(5)), - Token::MapSep, + Token::StructSep, Token::Str("whoops1"), Token::I32(2), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("whoops2"), Token::SeqStart(Some(1)), Token::SeqSep, Token::I32(2), Token::SeqEnd, - Token::MapSep, + Token::StructSep, Token::Str("a2"), Token::I32(2), - Token::MapSep, + Token::StructSep, Token::Str("whoops3"), Token::I32(2), - Token::MapSep, + Token::StructSep, Token::Str("a3"), Token::I32(3), - Token::MapEnd, + Token::StructEnd, ] ); @@ -158,15 +162,15 @@ fn test_ignore_unknown() { vec![ Token::StructStart("DenyUnknown", Some(2)), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("whoops"), Token::I32(2), - Token::MapEnd, + Token::StructEnd, ], Error::UnknownFieldError("whoops".to_owned()) ); @@ -195,15 +199,15 @@ fn test_rename_struct() { vec![ Token::StructStart("Superhero", Some(2)), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("a3"), Token::I32(2), - Token::MapEnd, + Token::StructEnd, ] ); @@ -212,15 +216,15 @@ fn test_rename_struct() { &[ Token::StructStart("SuperheroSer", Some(2)), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("a4"), Token::I32(2), - Token::MapEnd, + Token::StructEnd, ] ); @@ -229,15 +233,15 @@ fn test_rename_struct() { vec![ Token::StructStart("SuperheroDe", Some(2)), - Token::MapSep, + Token::StructSep, Token::Str("a1"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("a5"), Token::I32(2), - Token::MapEnd, + Token::StructEnd, ] ); } @@ -281,7 +285,7 @@ fn test_rename_enum() { assert_tokens( &RenameEnum::Superman(0), vec![ - Token::EnumNewtype("Superhero", "clark_kent"), + Token::EnumNewType("Superhero", "clark_kent"), Token::I8(0), ] ); @@ -291,13 +295,13 @@ fn test_rename_enum() { vec![ Token::EnumSeqStart("Superhero", "diana_prince", Some(2)), - Token::SeqSep, + Token::EnumSeqSep, Token::I8(0), - Token::SeqSep, + Token::EnumSeqSep, Token::I8(1), - Token::SeqEnd, + Token::EnumSeqEnd, ] ); @@ -306,11 +310,11 @@ fn test_rename_enum() { vec![ Token::EnumMapStart("Superhero", "barry_allan", Some(1)), - Token::MapSep, + Token::EnumMapSep, Token::Str("b"), Token::I32(1), - Token::MapEnd, + Token::EnumMapEnd, ] ); @@ -322,15 +326,15 @@ fn test_rename_enum() { &[ Token::EnumMapStart("SuperheroSer", "dick_grayson", Some(2)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I8(0), - Token::MapSep, + Token::EnumMapSep, Token::Str("c"), Token::Str(""), - Token::MapEnd, + Token::EnumMapEnd, ] ); @@ -342,24 +346,26 @@ fn test_rename_enum() { vec![ Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I8(0), - Token::MapSep, + Token::EnumMapSep, Token::Str("d"), Token::Str(""), - Token::MapEnd, + Token::EnumMapEnd, ] ); } #[derive(Debug, PartialEq, Serialize)] -struct SkipSerializingStruct<'a, B, D, E> { +struct SkipSerializingStruct<'a, B, C, D, E> where C: Trait { a: &'a i8, #[serde(skip_serializing)] b: B, + #[serde(skip_serializing_if="self.c.should_skip()")] + c: C, #[serde(skip_serializing_if_none)] d: Option, #[serde(skip_serializing_if_empty)] @@ -373,29 +379,34 @@ fn test_skip_serializing_struct() { &SkipSerializingStruct { a: &a, b: 2, + c: 3, d: Some(4), e: vec![5], }, &[ - Token::StructStart("SkipSerializingStruct", Some(3)), + Token::StructStart("SkipSerializingStruct", Some(4)), - Token::MapSep, + Token::StructSep, Token::Str("a"), Token::I8(1), - Token::MapSep, + Token::StructSep, + Token::Str("c"), + Token::I32(3), + + Token::StructSep, Token::Str("d"), Token::Option(true), Token::I32(4), - Token::MapSep, + Token::StructSep, Token::Str("e"), Token::SeqStart(Some(1)), Token::SeqSep, Token::I32(5), Token::SeqEnd, - Token::MapEnd, + Token::StructEnd, ] ); @@ -403,27 +414,30 @@ fn test_skip_serializing_struct() { &SkipSerializingStruct { a: &a, b: 2, + c: 123, d: None::, e: Vec::::new(), }, &[ Token::StructStart("SkipSerializingStruct", Some(1)), - Token::MapSep, + Token::StructSep, Token::Str("a"), Token::I8(1), - Token::MapEnd, + Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize)] -enum SkipSerializingEnum<'a, B, D, E> { +enum SkipSerializingEnum<'a, B, C, D, E> where C: Trait { Struct { a: &'a i8, #[serde(skip_serializing)] _b: B, + #[serde(skip_serializing_if="self.c.should_skip()")] + c: C, #[serde(skip_serializing_if_none)] d: Option, #[serde(skip_serializing_if_empty)] @@ -438,29 +452,34 @@ fn test_skip_serializing_enum() { &SkipSerializingEnum::Struct { a: &a, _b: 2, + c: 3, d: Some(4), e: vec![5], }, &[ - Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(3)), + Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(4)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::MapSep, + Token::EnumMapSep, + Token::Str("c"), + Token::I32(3), + + Token::EnumMapSep, Token::Str("d"), Token::Option(true), Token::I32(4), - Token::MapSep, + Token::EnumMapSep, Token::Str("e"), Token::SeqStart(Some(1)), Token::SeqSep, Token::I32(5), Token::SeqEnd, - Token::MapEnd, + Token::EnumMapEnd, ] ); @@ -468,17 +487,18 @@ fn test_skip_serializing_enum() { &SkipSerializingEnum::Struct { a: &a, _b: 2, + c: 123, d: None::, e: Vec::::new(), }, &[ Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::MapEnd, + Token::EnumMapEnd, ] ); } diff --git a/serde_tests/tests/test_de.rs b/serde_tests/tests/test_de.rs index 395e7645..dcc6e8f0 100644 --- a/serde_tests/tests/test_de.rs +++ b/serde_tests/tests/test_de.rs @@ -184,27 +184,27 @@ declare_tests! { ], TupleStruct(1, 2, 3) => vec![ Token::TupleStructStart("TupleStruct", Some(3)), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(1), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(2), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(3), - Token::SeqEnd, + Token::TupleSeqEnd, ], TupleStruct(1, 2, 3) => vec![ Token::TupleStructStart("TupleStruct", None), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(1), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(2), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(3), - Token::SeqEnd, + Token::TupleSeqEnd, ], } test_btreeset { @@ -495,18 +495,18 @@ declare_tests! { ], Struct { a: 1, b: 2, c: 3 } => vec![ Token::StructStart("Struct", Some(3)), - Token::MapSep, + Token::StructSep, Token::Str("a"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("b"), Token::I32(2), - Token::MapSep, + Token::StructSep, Token::Str("c"), Token::I32(3), - Token::MapEnd, + Token::StructEnd, ], } test_enum_unit { @@ -516,39 +516,39 @@ declare_tests! { } test_enum_simple { Enum::Simple(1) => vec![ - Token::EnumNewtype("Enum", "Simple"), + Token::EnumNewType("Enum", "Simple"), Token::I32(1), ], } test_enum_seq { Enum::Seq(1, 2, 3) => vec![ Token::EnumSeqStart("Enum", "Seq", Some(3)), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(1), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(2), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(3), - Token::SeqEnd, + Token::EnumSeqEnd, ], } test_enum_map { Enum::Map { a: 1, b: 2, c: 3 } => vec![ Token::EnumMapStart("Enum", "Map", Some(3)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I32(1), - Token::MapSep, + Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::MapSep, + Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::MapEnd, + Token::EnumMapEnd, ], } test_enum_unit_usize { diff --git a/serde_tests/tests/test_macros.rs b/serde_tests/tests/test_macros.rs index f8396fb7..842fa670 100644 --- a/serde_tests/tests/test_macros.rs +++ b/serde_tests/tests/test_macros.rs @@ -123,7 +123,7 @@ pub struct GenericStruct { } #[derive(Debug, PartialEq, Serialize, Deserialize)] -pub struct GenericNewtypeStruct(T); +pub struct GenericNewTypeStruct(T); #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct GenericTupleStruct(T, U); @@ -131,7 +131,7 @@ pub struct GenericTupleStruct(T, U); #[derive(Debug, PartialEq, Serialize, Deserialize)] pub enum GenericEnum { Unit, - Newtype(T), + NewType(T), Seq(T, U), Map { x: T, y: U }, } @@ -153,16 +153,16 @@ fn test_ser_named_tuple() { &SerNamedTuple(&a, &mut b, c), &[ Token::TupleStructStart("SerNamedTuple", Some(3)), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(5), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(6), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(7), - Token::SeqEnd, + Token::TupleSeqEnd, ], ); } @@ -172,7 +172,7 @@ fn test_de_named_tuple() { assert_de_tokens( &DeNamedTuple(5, 6, 7), vec![ - Token::TupleStructStart("DeNamedTuple", Some(3)), + Token::SeqStart(Some(3)), Token::SeqSep, Token::I32(5), @@ -185,6 +185,23 @@ fn test_de_named_tuple() { Token::SeqEnd, ] ); + + assert_de_tokens( + &DeNamedTuple(5, 6, 7), + vec![ + Token::TupleStructStart("DeNamedTuple", Some(3)), + Token::TupleSeqSep, + Token::I32(5), + + Token::TupleSeqSep, + Token::I32(6), + + Token::TupleSeqSep, + Token::I32(7), + + Token::TupleSeqEnd, + ] + ); } #[test] @@ -202,19 +219,19 @@ fn test_ser_named_map() { &[ Token::StructStart("SerNamedMap", Some(3)), - Token::MapSep, + Token::StructSep, Token::Str("a"), Token::I32(5), - Token::MapSep, + Token::StructSep, Token::Str("b"), Token::I32(6), - Token::MapSep, + Token::StructSep, Token::Str("c"), Token::I32(7), - Token::MapEnd, + Token::StructEnd, ] ); } @@ -230,19 +247,19 @@ fn test_de_named_map() { vec![ Token::StructStart("DeNamedMap", Some(3)), - Token::MapSep, + Token::StructSep, Token::Str("a"), Token::I32(5), - Token::MapSep, + Token::StructSep, Token::Str("b"), Token::I32(6), - Token::MapSep, + Token::StructSep, Token::Str("c"), Token::I32(7), - Token::MapEnd, + Token::StructEnd, ] ); } @@ -278,19 +295,19 @@ fn test_ser_enum_seq() { &[ Token::EnumSeqStart("SerEnum", "Seq", Some(4)), - Token::SeqSep, + Token::EnumSeqSep, Token::I8(1), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(2), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(3), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(5), - Token::SeqEnd, + Token::EnumSeqEnd, ], ); } @@ -316,23 +333,23 @@ fn test_ser_enum_map() { &[ Token::EnumMapStart("SerEnum", "Map", Some(4)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::MapSep, + Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::MapSep, + Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::MapSep, + Token::EnumMapSep, Token::Str("e"), Token::I32(5), - Token::MapEnd, + Token::EnumMapEnd, ], ); } @@ -368,19 +385,19 @@ fn test_de_enum_seq() { vec![ Token::EnumSeqStart("DeEnum", "Seq", Some(4)), - Token::SeqSep, + Token::EnumSeqSep, Token::I8(1), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(2), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(3), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(5), - Token::SeqEnd, + Token::EnumSeqEnd, ], ); } @@ -406,23 +423,23 @@ fn test_de_enum_map() { vec![ Token::EnumMapStart("DeEnum", "Map", Some(4)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I8(1), - Token::MapSep, + Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::MapSep, + Token::EnumMapSep, Token::Str("c"), Token::I32(3), - Token::MapSep, + Token::EnumMapSep, Token::Str("e"), Token::I32(5), - Token::MapEnd, + Token::EnumMapEnd, ], ); } @@ -434,7 +451,7 @@ fn test_lifetimes() { assert_ser_tokens( &Lifetimes::LifetimeSeq(&value), &[ - Token::EnumNewtype("Lifetimes", "LifetimeSeq"), + Token::EnumNewType("Lifetimes", "LifetimeSeq"), Token::I32(5), ] ); @@ -442,7 +459,7 @@ fn test_lifetimes() { assert_ser_tokens( &Lifetimes::NoLifetimeSeq(5), &[ - Token::EnumNewtype("Lifetimes", "NoLifetimeSeq"), + Token::EnumNewType("Lifetimes", "NoLifetimeSeq"), Token::I32(5), ] ); @@ -452,11 +469,11 @@ fn test_lifetimes() { &[ Token::EnumMapStart("Lifetimes", "LifetimeMap", Some(1)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I32(5), - Token::MapEnd, + Token::EnumMapEnd, ] ); @@ -465,11 +482,11 @@ fn test_lifetimes() { &[ Token::EnumMapStart("Lifetimes", "NoLifetimeMap", Some(1)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I32(5), - Token::MapEnd, + Token::EnumMapEnd, ] ); } @@ -481,11 +498,11 @@ fn test_generic_struct() { vec![ Token::StructStart("GenericStruct", Some(1)), - Token::MapSep, + Token::StructSep, Token::Str("x"), Token::U32(5), - Token::MapEnd, + Token::StructEnd, ] ); } @@ -493,9 +510,9 @@ fn test_generic_struct() { #[test] fn test_generic_newtype_struct() { assert_tokens( - &GenericNewtypeStruct(5u32), + &GenericNewTypeStruct(5u32), vec![ - Token::StructNewtype("GenericNewtypeStruct"), + Token::StructNewType("GenericNewTypeStruct"), Token::U32(5), ] ); @@ -508,13 +525,13 @@ fn test_generic_tuple_struct() { vec![ Token::TupleStructStart("GenericTupleStruct", Some(2)), - Token::SeqSep, + Token::TupleSeqSep, Token::U32(5), - Token::SeqSep, + Token::TupleSeqSep, Token::U32(6), - Token::SeqEnd, + Token::TupleSeqEnd, ] ); } @@ -532,9 +549,9 @@ fn test_generic_enum_unit() { #[test] fn test_generic_enum_newtype() { assert_tokens( - &GenericEnum::Newtype::(5), + &GenericEnum::NewType::(5), vec![ - Token::EnumNewtype("GenericEnum", "Newtype"), + Token::EnumNewType("GenericEnum", "NewType"), Token::U32(5), ] ); @@ -547,13 +564,13 @@ fn test_generic_enum_seq() { vec![ Token::EnumSeqStart("GenericEnum", "Seq", Some(2)), - Token::SeqSep, + Token::EnumSeqSep, Token::U32(5), - Token::SeqSep, + Token::EnumSeqSep, Token::U32(6), - Token::SeqEnd, + Token::EnumSeqEnd, ] ); } @@ -565,15 +582,15 @@ fn test_generic_enum_map() { vec![ Token::EnumMapStart("GenericEnum", "Map", Some(2)), - Token::MapSep, + Token::EnumMapSep, Token::Str("x"), Token::U32(5), - Token::MapSep, + Token::EnumMapSep, Token::Str("y"), Token::U32(6), - Token::MapEnd, + Token::EnumMapEnd, ] ); } diff --git a/serde_tests/tests/test_ser.rs b/serde_tests/tests/test_ser.rs index 77bf3eb8..e08d8c14 100644 --- a/serde_tests/tests/test_ser.rs +++ b/serde_tests/tests/test_ser.rs @@ -76,11 +76,11 @@ declare_ser_tests! { } test_result { Ok::(0) => &[ - Token::EnumNewtype("Result", "Ok"), + Token::EnumNewType("Result", "Ok"), Token::I32(0), ], Err::(1) => &[ - Token::EnumNewtype("Result", "Err"), + Token::EnumNewType("Result", "Err"), Token::I32(1), ], } @@ -214,56 +214,56 @@ declare_ser_tests! { test_tuple_struct { TupleStruct(1, 2, 3) => &[ Token::TupleStructStart("TupleStruct", Some(3)), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(1), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(2), - Token::SeqSep, + Token::TupleSeqSep, Token::I32(3), - Token::SeqEnd, + Token::TupleSeqEnd, ], } test_struct { Struct { a: 1, b: 2, c: 3 } => &[ Token::StructStart("Struct", Some(3)), - Token::MapSep, + Token::StructSep, Token::Str("a"), Token::I32(1), - Token::MapSep, + Token::StructSep, Token::Str("b"), Token::I32(2), - Token::MapSep, + Token::StructSep, Token::Str("c"), Token::I32(3), - Token::MapEnd, + Token::StructEnd, ], } test_enum { Enum::Unit => &[Token::EnumUnit("Enum", "Unit")], - Enum::One(42) => &[Token::EnumNewtype("Enum", "One"), Token::I32(42)], + Enum::One(42) => &[Token::EnumNewType("Enum", "One"), Token::I32(42)], Enum::Seq(1, 2) => &[ Token::EnumSeqStart("Enum", "Seq", Some(2)), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(1), - Token::SeqSep, + Token::EnumSeqSep, Token::I32(2), - Token::SeqEnd, + Token::EnumSeqEnd, ], Enum::Map { a: 1, b: 2 } => &[ Token::EnumMapStart("Enum", "Map", Some(2)), - Token::MapSep, + Token::EnumMapSep, Token::Str("a"), Token::I32(1), - Token::MapSep, + Token::EnumMapSep, Token::Str("b"), Token::I32(2), - Token::MapEnd, + Token::EnumMapEnd, ], } test_num_bigint { diff --git a/serde_tests/tests/token.rs b/serde_tests/tests/token.rs index 1b14a7d3..40810d47 100644 --- a/serde_tests/tests/token.rs +++ b/serde_tests/tests/token.rs @@ -2,7 +2,8 @@ use std::fmt; use std::iter; use std::error; -use serde::{ser, de}; +use serde::ser::{self, Serialize}; +use serde::de; use serde::de::value::{self, ValueDeserializer}; #[derive(Clone, PartialEq, Debug)] @@ -30,23 +31,35 @@ pub enum Token<'a> { Unit, UnitStruct(&'a str), - StructNewtype(&'a str), + StructNewType(&'a str), EnumStart(&'a str), EnumUnit(&'a str, &'a str), - EnumNewtype(&'a str, &'a str), - EnumSeqStart(&'a str, &'a str, Option), - EnumMapStart(&'a str, &'a str, Option), + EnumNewType(&'a str, &'a str), SeqStart(Option), - TupleStructStart(&'a str, Option), SeqSep, SeqEnd, + TupleStructStart(&'a str, Option), + TupleSeqSep, + TupleSeqEnd, + MapStart(Option), - StructStart(&'a str, Option), MapSep, MapEnd, + + StructStart(&'a str, Option), + StructSep, + StructEnd, + + EnumSeqStart(&'a str, &'a str, Option), + EnumSeqSep, + EnumSeqEnd, + + EnumMapStart(&'a str, &'a str, Option), + EnumMapSep, + EnumMapEnd, } ////////////////////////////////////////////////////////////////////////////// @@ -102,7 +115,7 @@ impl<'a, I> ser::Serializer for Serializer value: T) -> Result<(), Error> where T: ser::Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::EnumNewtype(name, variant))); + assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant))); value.serialize(self) } @@ -218,43 +231,65 @@ impl<'a, I> ser::Serializer for Serializer self.visit_sequence(visitor) } + fn serialize_seq_elt(&mut self, value: T) -> Result<(), Error> + where T: ser::Serialize + { + assert_eq!(self.tokens.next(), Some(&Token::SeqSep)); + value.serialize(self) + } + fn serialize_newtype_struct(&mut self, name: &'static str, value: T) -> Result<(), Error> where T: ser::Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::StructNewtype(name))); + assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name))); value.serialize(self) } - fn serialize_tuple_struct(&mut self, name: &str, visitor: V) -> Result<(), Error> + fn serialize_tuple_struct(&mut self, name: &str, mut visitor: V) -> Result<(), Error> where V: ser::SeqVisitor { let len = visitor.len(); assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len))); - self.visit_sequence(visitor) + while let Some(()) = try!(visitor.visit(self)) { } + + assert_eq!(self.tokens.next(), Some(&Token::TupleSeqEnd)); + + Ok(()) + } + + fn serialize_tuple_struct_elt(&mut self, value: T) -> Result<(), Error> + where T: ser::Serialize, + { + assert_eq!(self.tokens.next(), Some(&Token::TupleSeqSep)); + value.serialize(self) } fn serialize_tuple_variant(&mut self, - name: &str, - _variant_index: usize, - variant: &str, - visitor: V) -> Result<(), Error> + name: &str, + _variant_index: usize, + variant: &str, + mut visitor: V) -> Result<(), Error> where V: ser::SeqVisitor { let len = visitor.len(); assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len))); - self.visit_sequence(visitor) + while let Some(()) = try!(visitor.visit(self)) { } + + assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd)); + + Ok(()) } - fn serialize_seq_elt(&mut self, value: T) -> Result<(), Error> - where T: ser::Serialize + fn serialize_tuple_variant_elt(&mut self, value: T) -> Result<(), Error> + where T: ser::Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::SeqSep)); + assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep)); value.serialize(self) } @@ -268,35 +303,61 @@ impl<'a, I> ser::Serializer for Serializer self.visit_mapping(visitor) } - fn serialize_struct(&mut self, name: &str, visitor: V) -> Result<(), Error> + fn serialize_map_elt(&mut self, key: K, value: V) -> Result<(), Error> + where K: ser::Serialize, + V: ser::Serialize, + { + assert_eq!(self.tokens.next(), Some(&Token::MapSep)); + + try!(key.serialize(self)); + value.serialize(self) + } + + fn serialize_struct(&mut self, name: &str, mut visitor: V) -> Result<(), Error> where V: ser::MapVisitor { let len = visitor.len(); assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len))); - self.visit_mapping(visitor) + while let Some(()) = try!(visitor.visit(self)) { } + + assert_eq!(self.tokens.next(), Some(&Token::StructEnd)); + + Ok(()) + } + + fn serialize_struct_elt(&mut self, key: &'static str, value: T) -> Result<(), Error> + where T: ser::Serialize, + { + assert_eq!(self.tokens.next(), Some(&Token::StructSep)); + + try!(key.serialize(self)); + value.serialize(self) } fn serialize_struct_variant(&mut self, - name: &str, - _variant_index: usize, - variant: &str, - visitor: V) -> Result<(), Error> + name: &str, + _variant_index: usize, + variant: &str, + mut visitor: V) -> Result<(), Error> where V: ser::MapVisitor { let len = visitor.len(); assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len))); - self.visit_mapping(visitor) + while let Some(()) = try!(visitor.visit(self)) { } + + assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd)); + + Ok(()) } - fn serialize_map_elt(&mut self, key: K, value: V) -> Result<(), Error> - where K: ser::Serialize, - V: ser::Serialize, + fn serialize_struct_variant_elt(&mut self, key: &'static str, value: T) -> Result<(), Error> + where T: ser::Serialize, { - assert_eq!(self.tokens.next(), Some(&Token::MapSep)); + assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep)); try!(key.serialize(self)); value.serialize(self) @@ -383,6 +444,24 @@ impl Deserializer }) } + fn visit_tuple_seq(&mut self, len: Option, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_seq(DeserializerTupleSeqVisitor { + de: self, + len: len, + }) + } + + fn visit_variant_seq(&mut self, len: Option, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_seq(DeserializerVariantSeqVisitor { + de: self, + len: len, + }) + } + fn visit_map(&mut self, len: Option, mut visitor: V) -> Result where V: de::Visitor, { @@ -391,6 +470,24 @@ impl Deserializer len: len, }) } + + fn visit_struct(&mut self, len: Option, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_map(DeserializerStructVisitor { + de: self, + len: len, + }) + } + + fn visit_variant_map(&mut self, len: Option, mut visitor: V) -> Result + where V: de::Visitor, + { + visitor.visit_map(DeserializerVariantMapVisitor { + de: self, + len: len, + }) + } } impl de::Deserializer for Deserializer @@ -429,7 +526,6 @@ impl de::Deserializer for Deserializer Some(Token::MapStart(len)) | Some(Token::StructStart(_, len)) => { self.visit_map(len, visitor) } - //Some(Token::Name(_)) => self.visit(visitor), Some(token) => Err(Error::UnexpectedToken(token)), None => Err(Error::EndOfStreamError), } @@ -473,7 +569,7 @@ impl de::Deserializer for Deserializer }) } Some(&Token::EnumUnit(n, _)) - | Some(&Token::EnumNewtype(n, _)) + | Some(&Token::EnumNewType(n, _)) | Some(&Token::EnumSeqStart(n, _, _)) | Some(&Token::EnumMapStart(n, _, _)) if name == n => { visitor.visit(DeserializerVariantVisitor { @@ -506,12 +602,12 @@ impl de::Deserializer for Deserializer } fn deserialize_newtype_struct(&mut self, - name: &str, - mut visitor: V) -> Result + name: &str, + mut visitor: V) -> Result where V: de::Visitor, { match self.tokens.peek() { - Some(&Token::StructNewtype(n)) => { + Some(&Token::StructNewType(n)) => { self.tokens.next(); if name == n { visitor.visit_newtype_struct(self) @@ -525,9 +621,9 @@ impl de::Deserializer for Deserializer } fn deserialize_tuple_struct(&mut self, - name: &str, - len: usize, - mut visitor: V) -> Result + name: &str, + len: usize, + mut visitor: V) -> Result where V: de::Visitor, { match self.tokens.peek() { @@ -542,7 +638,7 @@ impl de::Deserializer for Deserializer Some(&Token::TupleStructStart(n, _)) => { self.tokens.next(); if name == n { - self.visit_seq(Some(len), visitor) + self.visit_tuple_seq(Some(len), visitor) } else { Err(Error::InvalidName(n)) } @@ -557,16 +653,16 @@ impl de::Deserializer for Deserializer } fn deserialize_struct(&mut self, - name: &str, - fields: &'static [&'static str], - visitor: V) -> Result + name: &str, + fields: &'static [&'static str], + visitor: V) -> Result where V: de::Visitor, { match self.tokens.peek() { Some(&Token::StructStart(n, _)) => { self.tokens.next(); if name == n { - self.visit_map(Some(fields.len()), visitor) + self.visit_struct(Some(fields.len()), visitor) } else { Err(Error::InvalidName(n)) } @@ -628,6 +724,96 @@ impl<'a, I> de::SeqVisitor for DeserializerSeqVisitor<'a, I> ////////////////////////////////////////////////////////////////////////// +struct DeserializerTupleSeqVisitor<'a, I: 'a> where I: Iterator> { + de: &'a mut Deserializer, + len: Option, +} + +impl<'a, I> de::SeqVisitor for DeserializerTupleSeqVisitor<'a, I> + where I: Iterator>, +{ + type Error = Error; + + fn visit(&mut self) -> Result, Error> + where T: de::Deserialize, + { + match self.de.tokens.peek() { + Some(&Token::TupleSeqSep) => { + self.de.tokens.next(); + self.len = self.len.map(|len| len - 1); + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) + } + Some(&Token::TupleSeqEnd) => Ok(None), + Some(_) => { + let token = self.de.tokens.next().unwrap(); + Err(Error::UnexpectedToken(token)) + } + None => Err(Error::EndOfStreamError), + } + } + + fn end(&mut self) -> Result<(), Error> { + //assert_eq!(self.len.unwrap_or(0), 0); + match self.de.tokens.next() { + Some(Token::TupleSeqEnd) => Ok(()), + Some(token) => Err(Error::UnexpectedToken(token)), + None => Err(Error::EndOfStreamError), + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len.unwrap_or(0); + (len, self.len) + } +} + +////////////////////////////////////////////////////////////////////////// + +struct DeserializerVariantSeqVisitor<'a, I: 'a> where I: Iterator> { + de: &'a mut Deserializer, + len: Option, +} + +impl<'a, I> de::SeqVisitor for DeserializerVariantSeqVisitor<'a, I> + where I: Iterator>, +{ + type Error = Error; + + fn visit(&mut self) -> Result, Error> + where T: de::Deserialize, + { + match self.de.tokens.peek() { + Some(&Token::EnumSeqSep) => { + self.de.tokens.next(); + self.len = self.len.map(|len| len - 1); + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) + } + Some(&Token::EnumSeqEnd) => Ok(None), + Some(_) => { + let token = self.de.tokens.next().unwrap(); + Err(Error::UnexpectedToken(token)) + } + None => Err(Error::EndOfStreamError), + } + } + + fn end(&mut self) -> Result<(), Error> { + //assert_eq!(self.len.unwrap_or(0), 0); + match self.de.tokens.next() { + Some(Token::EnumSeqEnd) => Ok(()), + Some(token) => Err(Error::UnexpectedToken(token)), + None => Err(Error::EndOfStreamError), + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len.unwrap_or(0); + (len, self.len) + } +} + +////////////////////////////////////////////////////////////////////////// + struct DeserializerMapVisitor<'a, I: 'a> where I: Iterator> { de: &'a mut Deserializer, len: Option, @@ -679,6 +865,57 @@ impl<'a, I> de::MapVisitor for DeserializerMapVisitor<'a, I> ////////////////////////////////////////////////////////////////////////// +struct DeserializerStructVisitor<'a, I: 'a> where I: Iterator> { + de: &'a mut Deserializer, + len: Option, +} + +impl<'a, I> de::MapVisitor for DeserializerStructVisitor<'a, I> + where I: Iterator>, +{ + type Error = Error; + + fn visit_key(&mut self) -> Result, Error> + where K: de::Deserialize, + { + match self.de.tokens.peek() { + Some(&Token::StructSep) => { + self.de.tokens.next(); + self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 }); + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) + } + Some(&Token::StructEnd) => Ok(None), + Some(_) => { + let token = self.de.tokens.next().unwrap(); + Err(Error::UnexpectedToken(token)) + } + None => Err(Error::EndOfStreamError), + } + } + + fn visit_value(&mut self) -> Result + where V: de::Deserialize, + { + Ok(try!(de::Deserialize::deserialize(self.de))) + } + + fn end(&mut self) -> Result<(), Error> { + //assert_eq!(self.len.unwrap_or(0), 0); + match self.de.tokens.next() { + Some(Token::StructEnd) => Ok(()), + Some(token) => Err(Error::UnexpectedToken(token)), + None => Err(Error::EndOfStreamError), + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len.unwrap_or(0); + (len, self.len) + } +} + +////////////////////////////////////////////////////////////////////////// + struct DeserializerVariantVisitor<'a, I: 'a> where I: Iterator> { de: &'a mut Deserializer, } @@ -693,7 +930,7 @@ impl<'a, I> de::VariantVisitor for DeserializerVariantVisitor<'a, I> { match self.de.tokens.peek() { Some(&Token::EnumUnit(_, v)) - | Some(&Token::EnumNewtype(_, v)) + | Some(&Token::EnumNewType(_, v)) | Some(&Token::EnumSeqStart(_, v, _)) | Some(&Token::EnumMapStart(_, v, _)) => { let mut de = ValueDeserializer::::into_deserializer(v); @@ -724,7 +961,7 @@ impl<'a, I> de::VariantVisitor for DeserializerVariantVisitor<'a, I> where T: de::Deserialize, { match self.de.tokens.peek() { - Some(&Token::EnumNewtype(_, _)) => { + Some(&Token::EnumNewType(_, _)) => { self.de.tokens.next(); de::Deserialize::deserialize(self.de) } @@ -744,6 +981,15 @@ impl<'a, I> de::VariantVisitor for DeserializerVariantVisitor<'a, I> Some(&Token::EnumSeqStart(_, _, Some(enum_len))) => { let token = self.de.tokens.next().unwrap(); + if len == enum_len { + self.de.visit_variant_seq(Some(len), visitor) + } else { + Err(Error::UnexpectedToken(token)) + } + } + Some(&Token::SeqStart(Some(enum_len))) => { + let token = self.de.tokens.next().unwrap(); + if len == enum_len { self.de.visit_seq(Some(len), visitor) } else { @@ -766,6 +1012,15 @@ impl<'a, I> de::VariantVisitor for DeserializerVariantVisitor<'a, I> Some(&Token::EnumMapStart(_, _, Some(enum_len))) => { let token = self.de.tokens.next().unwrap(); + if fields.len() == enum_len { + self.de.visit_variant_map(Some(fields.len()), visitor) + } else { + Err(Error::UnexpectedToken(token)) + } + } + Some(&Token::MapStart(Some(enum_len))) => { + let token = self.de.tokens.next().unwrap(); + if fields.len() == enum_len { self.de.visit_map(Some(fields.len()), visitor) } else { @@ -780,6 +1035,57 @@ impl<'a, I> de::VariantVisitor for DeserializerVariantVisitor<'a, I> } } +////////////////////////////////////////////////////////////////////////// + +struct DeserializerVariantMapVisitor<'a, I: 'a> where I: Iterator> { + de: &'a mut Deserializer, + len: Option, +} + +impl<'a, I> de::MapVisitor for DeserializerVariantMapVisitor<'a, I> + where I: Iterator>, +{ + type Error = Error; + + fn visit_key(&mut self) -> Result, Error> + where K: de::Deserialize, + { + match self.de.tokens.peek() { + Some(&Token::EnumMapSep) => { + self.de.tokens.next(); + self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 }); + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) + } + Some(&Token::EnumMapEnd) => Ok(None), + Some(_) => { + let token = self.de.tokens.next().unwrap(); + Err(Error::UnexpectedToken(token)) + } + None => Err(Error::EndOfStreamError), + } + } + + fn visit_value(&mut self) -> Result + where V: de::Deserialize, + { + Ok(try!(de::Deserialize::deserialize(self.de))) + } + + fn end(&mut self) -> Result<(), Error> { + //assert_eq!(self.len.unwrap_or(0), 0); + match self.de.tokens.next() { + Some(Token::EnumMapEnd) => Ok(()), + Some(token) => Err(Error::UnexpectedToken(token)), + None => Err(Error::EndOfStreamError), + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len.unwrap_or(0); + (len, self.len) + } +} + ////////////////////////////////////////////////////////////////////////////// pub fn assert_ser_tokens(value: &T, tokens: &[Token])