feat(codegen): Add support for #![serde(skip_serialize_if="$expr")]

This allows end users to use an arbitrary expression to decide whether
or not to serialize some field. This expression has access to all the
fields in the struct, but none of the internal state of the Serialize
implementation. For structs, serde implements this by creating a
temporary trait and implementing the struct for it. For struct variants,
the fields are copied by reference into a temporary struct first
before implementing the temporary trait.

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