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
+79 -59
View File
@@ -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<D>,
#[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::<u8>,
e: Vec::<u8>::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<D>,
#[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::<u8>,
e: Vec::<u8>::new(),
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)),
Token::MapSep,
Token::EnumMapSep,
Token::Str("a"),
Token::I8(1),
Token::MapEnd,
Token::EnumMapEnd,
]
);
}
+21 -21
View File
@@ -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 {
+73 -56
View File
@@ -123,7 +123,7 @@ pub struct GenericStruct<T> {
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericNewtypeStruct<T>(T);
pub struct GenericNewTypeStruct<T>(T);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct GenericTupleStruct<T, U>(T, U);
@@ -131,7 +131,7 @@ pub struct GenericTupleStruct<T, U>(T, U);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum GenericEnum<T, U> {
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::<u32, u32>(5),
&GenericEnum::NewType::<u32, u32>(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,
]
);
}
+17 -17
View File
@@ -76,11 +76,11 @@ declare_ser_tests! {
}
test_result {
Ok::<i32, i32>(0) => &[
Token::EnumNewtype("Result", "Ok"),
Token::EnumNewType("Result", "Ok"),
Token::I32(0),
],
Err::<i32, i32>(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 {
+351 -45
View File
@@ -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<usize>),
EnumMapStart(&'a str, &'a str, Option<usize>),
EnumNewType(&'a str, &'a str),
SeqStart(Option<usize>),
TupleStructStart(&'a str, Option<usize>),
SeqSep,
SeqEnd,
TupleStructStart(&'a str, Option<usize>),
TupleSeqSep,
TupleSeqEnd,
MapStart(Option<usize>),
StructStart(&'a str, Option<usize>),
MapSep,
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>
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<I>
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,
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<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
{
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<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,
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<T>(&mut self, value: T) -> Result<(), Error>
where T: ser::Serialize
fn serialize_tuple_variant_elt<T>(&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<I>
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
{
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<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,
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<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
where K: ser::Serialize,
V: ser::Serialize,
fn serialize_struct_variant_elt<T>(&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<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>
where V: de::Visitor,
{
@@ -391,6 +470,24 @@ impl<I> Deserializer<I>
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>
@@ -429,7 +526,6 @@ impl<I> de::Deserializer for Deserializer<I>
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<I> de::Deserializer for Deserializer<I>
})
}
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<I> de::Deserializer for Deserializer<I>
}
fn deserialize_newtype_struct<V>(&mut self,
name: &str,
mut visitor: V) -> Result<V::Value, Error>
name: &str,
mut visitor: V) -> Result<V::Value, Error>
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<I> de::Deserializer for Deserializer<I>
}
fn deserialize_tuple_struct<V>(&mut self,
name: &str,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
name: &str,
len: usize,
mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
@@ -542,7 +638,7 @@ impl<I> de::Deserializer for Deserializer<I>
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<I> de::Deserializer for Deserializer<I>
}
fn deserialize_struct<V>(&mut self,
name: &str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
name: &str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Error>
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<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>> {
de: &'a mut Deserializer<I>,
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>> {
de: &'a mut Deserializer<I>,
}
@@ -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::<Error>::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<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])