extern crate serde; use self::serde::{Serialize, Serializer, Deserialize, Deserializer}; use token::{ Error, Token, assert_tokens, assert_ser_tokens, assert_de_tokens, assert_de_tokens_error }; trait MyDefault: Sized { fn my_default() -> Self; } trait ShouldSkip: Sized { fn should_skip(&self) -> bool; } trait SerializeWith: Sized { fn serialize_with(&self, ser: &mut S) -> Result<(), S::Error> where S: Serializer; } trait DeserializeWith: Sized { fn deserialize_with(de: &mut D) -> Result where D: Deserializer; } impl MyDefault for i32 { fn my_default() -> Self { 123 } } impl ShouldSkip for i32 { fn should_skip(&self) -> bool { *self == 123 } } impl SerializeWith for i32 { fn serialize_with(&self, ser: &mut S) -> Result<(), S::Error> where S: Serializer { if *self == 123 { true.serialize(ser) } else { false.serialize(ser) } } } impl DeserializeWith for i32 { fn deserialize_with(de: &mut D) -> Result where D: Deserializer { if try!(Deserialize::deserialize(de)) { Ok(123) } else { Ok(2) } } } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct DefaultStruct where C: MyDefault, E: MyDefault, { a1: A, #[serde(default)] a2: B, #[serde(default="MyDefault::my_default")] a3: C, #[serde(skip_deserializing)] a4: D, #[serde(skip_deserializing, default="MyDefault::my_default")] a5: E, } #[test] fn test_default_struct() { assert_de_tokens( &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, vec![ Token::StructStart("DefaultStruct", Some(3)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructSep, Token::Str("a2"), Token::I32(2), Token::StructSep, Token::Str("a3"), Token::I32(3), Token::StructSep, Token::Str("a4"), Token::I32(4), Token::StructSep, Token::Str("a5"), Token::I32(5), Token::StructEnd, ] ); assert_de_tokens( &DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 }, vec![ Token::StructStart("DefaultStruct", Some(1)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum DefaultEnum where C: MyDefault, E: MyDefault { Struct { a1: A, #[serde(default)] a2: B, #[serde(default="MyDefault::my_default")] a3: C, #[serde(skip_deserializing)] a4: D, #[serde(skip_deserializing, default="MyDefault::my_default")] a5: E, } } #[test] fn test_default_enum() { assert_de_tokens( &DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, vec![ Token::EnumMapStart("DefaultEnum", "Struct", Some(5)), Token::EnumMapSep, Token::Str("a1"), Token::I32(1), Token::EnumMapSep, Token::Str("a2"), Token::I32(2), Token::EnumMapSep, Token::Str("a3"), Token::I32(3), Token::EnumMapSep, Token::Str("a4"), Token::I32(4), Token::EnumMapSep, Token::Str("a5"), Token::I32(5), Token::EnumMapEnd, ] ); assert_de_tokens( &DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 }, vec![ Token::EnumMapStart("DefaultEnum", "Struct", Some(5)), Token::EnumMapSep, Token::Str("a1"), Token::I32(1), Token::EnumMapEnd, ] ); } // Does not implement std::default::Default. #[derive(Debug, PartialEq, Deserialize)] struct NoStdDefault(i8); impl MyDefault for NoStdDefault { fn my_default() -> Self { NoStdDefault(123) } } #[derive(Debug, PartialEq, Deserialize)] struct ContainsNoStdDefault { #[serde(default="MyDefault::my_default")] a: A, } // Tests that a struct field does not need to implement std::default::Default if // it is annotated with `default=...`. #[test] fn test_no_std_default() { assert_de_tokens( &ContainsNoStdDefault { a: NoStdDefault(123) }, vec![ Token::StructStart("ContainsNoStdDefault", Some(1)), Token::StructEnd, ] ); assert_de_tokens( &ContainsNoStdDefault { a: NoStdDefault(8) }, vec![ Token::StructStart("ContainsNoStdDefault", Some(1)), Token::StructSep, Token::Str("a"), Token::StructNewType("NoStdDefault"), Token::I8(8), Token::StructEnd, ] ); } // Does not implement Deserialize. #[derive(Debug, PartialEq)] struct NotDeserializeStruct(i8); impl Default for NotDeserializeStruct { fn default() -> Self { NotDeserializeStruct(123) } } impl DeserializeWith for NotDeserializeStruct { fn deserialize_with(_: &mut D) -> Result where D: Deserializer { panic!() } } // Does not implement Deserialize. #[derive(Debug, PartialEq)] enum NotDeserializeEnum { Trouble } impl MyDefault for NotDeserializeEnum { fn my_default() -> Self { NotDeserializeEnum::Trouble } } #[derive(Debug, PartialEq, Deserialize)] struct ContainsNotDeserialize { #[serde(skip_deserializing)] a: A, #[serde(skip_deserializing, default)] b: B, #[serde(deserialize_with="DeserializeWith::deserialize_with", default)] c: C, #[serde(skip_deserializing, default="MyDefault::my_default")] e: E, } // Tests that a struct field does not need to implement Deserialize if it is // annotated with skip_deserializing, whether using the std Default or a // custom default. #[test] fn test_elt_not_deserialize() { assert_de_tokens( &ContainsNotDeserialize { a: NotDeserializeStruct(123), b: NotDeserializeStruct(123), c: NotDeserializeStruct(123), e: NotDeserializeEnum::Trouble, }, vec![ Token::StructStart("ContainsNotDeserialize", Some(3)), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] struct DenyUnknown { a1: i32, } #[test] fn test_ignore_unknown() { // 'Default' allows unknown. Basic smoke test of ignore... assert_de_tokens( &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 }, vec![ Token::StructStart("DefaultStruct", Some(5)), Token::StructSep, Token::Str("whoops1"), Token::I32(2), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructSep, Token::Str("whoops2"), Token::SeqStart(Some(1)), Token::SeqSep, Token::I32(2), Token::SeqEnd, Token::StructSep, Token::Str("a2"), Token::I32(2), Token::StructSep, Token::Str("whoops3"), Token::I32(2), Token::StructSep, Token::Str("a3"), Token::I32(3), Token::StructEnd, ] ); assert_de_tokens_error::( vec![ Token::StructStart("DenyUnknown", Some(2)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructSep, Token::Str("whoops"), Token::I32(2), Token::StructEnd, ], Error::UnknownFieldError("whoops".to_owned()) ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename="Superhero")] struct RenameStruct { a1: i32, #[serde(rename="a3")] a2: i32, } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))] struct RenameStructSerializeDeserialize { a1: i32, #[serde(rename(serialize="a4", deserialize="a5"))] a2: i32, } #[test] fn test_rename_struct() { assert_tokens( &RenameStruct { a1: 1, a2: 2 }, vec![ Token::StructStart("Superhero", Some(2)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructSep, Token::Str("a3"), Token::I32(2), Token::StructEnd, ] ); assert_ser_tokens( &RenameStructSerializeDeserialize { a1: 1, a2: 2 }, &[ Token::StructStart("SuperheroSer", Some(2)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructSep, Token::Str("a4"), Token::I32(2), Token::StructEnd, ] ); assert_de_tokens( &RenameStructSerializeDeserialize { a1: 1, a2: 2 }, vec![ Token::StructStart("SuperheroDe", Some(2)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructSep, Token::Str("a5"), Token::I32(2), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename="Superhero")] enum RenameEnum { #[serde(rename="bruce_wayne")] Batman, #[serde(rename="clark_kent")] Superman(i8), #[serde(rename="diana_prince")] WonderWoman(i8, i8), #[serde(rename="barry_allan")] Flash { #[serde(rename="b")] a: i32, }, } #[derive(Debug, PartialEq, Deserialize, Serialize)] #[serde(rename(serialize="SuperheroSer", deserialize="SuperheroDe"))] enum RenameEnumSerializeDeserialize { #[serde(rename(serialize="dick_grayson", deserialize="jason_todd"))] Robin { a: i8, #[serde(rename(serialize="c"))] #[serde(rename(deserialize="d"))] b: A, }, } #[test] fn test_rename_enum() { assert_tokens( &RenameEnum::Batman, vec![ Token::EnumUnit("Superhero", "bruce_wayne"), ] ); assert_tokens( &RenameEnum::Superman(0), vec![ Token::EnumNewType("Superhero", "clark_kent"), Token::I8(0), ] ); assert_tokens( &RenameEnum::WonderWoman(0, 1), vec![ Token::EnumSeqStart("Superhero", "diana_prince", Some(2)), Token::EnumSeqSep, Token::I8(0), Token::EnumSeqSep, Token::I8(1), Token::EnumSeqEnd, ] ); assert_tokens( &RenameEnum::Flash { a: 1 }, vec![ Token::EnumMapStart("Superhero", "barry_allan", Some(1)), Token::EnumMapSep, Token::Str("b"), Token::I32(1), Token::EnumMapEnd, ] ); assert_ser_tokens( &RenameEnumSerializeDeserialize::Robin { a: 0, b: String::new(), }, &[ Token::EnumMapStart("SuperheroSer", "dick_grayson", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(0), Token::EnumMapSep, Token::Str("c"), Token::Str(""), Token::EnumMapEnd, ] ); assert_de_tokens( &RenameEnumSerializeDeserialize::Robin { a: 0, b: String::new(), }, vec![ Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(0), Token::EnumMapSep, Token::Str("d"), Token::Str(""), Token::EnumMapEnd, ] ); } #[derive(Debug, PartialEq, Serialize)] struct SkipSerializingStruct<'a, B, C> where C: ShouldSkip { a: &'a i8, #[serde(skip_serializing)] b: B, #[serde(skip_serializing_if="ShouldSkip::should_skip")] c: C, } #[test] fn test_skip_serializing_struct() { let a = 1; assert_ser_tokens( &SkipSerializingStruct { a: &a, b: 2, c: 3, }, &[ Token::StructStart("SkipSerializingStruct", Some(2)), Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructSep, Token::Str("c"), Token::I32(3), Token::StructEnd, ] ); assert_ser_tokens( &SkipSerializingStruct { a: &a, b: 2, c: 123, }, &[ Token::StructStart("SkipSerializingStruct", Some(1)), Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize)] enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip { Struct { a: &'a i8, #[serde(skip_serializing)] _b: B, #[serde(skip_serializing_if="ShouldSkip::should_skip")] c: C, } } #[test] fn test_skip_serializing_enum() { let a = 1; assert_ser_tokens( &SkipSerializingEnum::Struct { a: &a, _b: 2, c: 3, }, &[ Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(1), Token::EnumMapSep, Token::Str("c"), Token::I32(3), Token::EnumMapEnd, ] ); assert_ser_tokens( &SkipSerializingEnum::Struct { a: &a, _b: 2, c: 123, }, &[ Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)), Token::EnumMapSep, Token::Str("a"), Token::I8(1), Token::EnumMapEnd, ] ); } #[derive(Debug, PartialEq)] struct NotSerializeStruct(i8); #[derive(Debug, PartialEq)] enum NotSerializeEnum { Trouble } impl SerializeWith for NotSerializeEnum { fn serialize_with(&self, ser: &mut S) -> Result<(), S::Error> where S: Serializer { "trouble".serialize(ser) } } #[derive(Debug, PartialEq, Serialize)] struct ContainsNotSerialize<'a, B, C, D> where B: 'a, D: SerializeWith { a: &'a Option, #[serde(skip_serializing)] b: &'a B, #[serde(skip_serializing)] c: Option, #[serde(serialize_with="SerializeWith::serialize_with")] d: D, } #[test] fn test_elt_not_serialize() { let a = 1; assert_ser_tokens( &ContainsNotSerialize { a: &Some(a), b: &NotSerializeStruct(2), c: Some(NotSerializeEnum::Trouble), d: NotSerializeEnum::Trouble, }, &[ Token::StructStart("ContainsNotSerialize", Some(2)), Token::StructSep, Token::Str("a"), Token::Option(true), Token::I8(1), Token::StructSep, Token::Str("d"), Token::Str("trouble"), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize)] struct SerializeWithStruct<'a, B> where B: SerializeWith { a: &'a i8, #[serde(serialize_with="SerializeWith::serialize_with")] b: B, } #[test] fn test_serialize_with_struct() { let a = 1; assert_ser_tokens( &SerializeWithStruct { a: &a, b: 2, }, &[ Token::StructStart("SerializeWithStruct", Some(2)), Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructSep, Token::Str("b"), Token::Bool(false), Token::StructEnd, ] ); assert_ser_tokens( &SerializeWithStruct { a: &a, b: 123, }, &[ Token::StructStart("SerializeWithStruct", Some(2)), Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructSep, Token::Str("b"), Token::Bool(true), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Serialize)] enum SerializeWithEnum<'a, B> where B: SerializeWith { Struct { a: &'a i8, #[serde(serialize_with="SerializeWith::serialize_with")] b: B, } } #[test] fn test_serialize_with_enum() { let a = 1; assert_ser_tokens( &SerializeWithEnum::Struct { a: &a, b: 2, }, &[ Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(1), Token::EnumMapSep, Token::Str("b"), Token::Bool(false), Token::EnumMapEnd, ] ); assert_ser_tokens( &SerializeWithEnum::Struct { a: &a, b: 123, }, &[ Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(1), Token::EnumMapSep, Token::Str("b"), Token::Bool(true), Token::EnumMapEnd, ] ); } #[derive(Debug, PartialEq, Deserialize)] struct DeserializeWithStruct where B: DeserializeWith { a: i8, #[serde(deserialize_with="DeserializeWith::deserialize_with")] b: B, } #[test] fn test_deserialize_with_struct() { assert_de_tokens( &DeserializeWithStruct { a: 1, b: 2, }, vec![ Token::StructStart("DeserializeWithStruct", Some(2)), Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructSep, Token::Str("b"), Token::Bool(false), Token::StructEnd, ] ); assert_de_tokens( &DeserializeWithStruct { a: 1, b: 123, }, vec![ Token::StructStart("DeserializeWithStruct", Some(2)), Token::StructSep, Token::Str("a"), Token::I8(1), Token::StructSep, Token::Str("b"), Token::Bool(true), Token::StructEnd, ] ); } #[derive(Debug, PartialEq, Deserialize)] enum DeserializeWithEnum where B: DeserializeWith { Struct { a: i8, #[serde(deserialize_with="DeserializeWith::deserialize_with")] b: B, } } #[test] fn test_deserialize_with_enum() { assert_de_tokens( &DeserializeWithEnum::Struct { a: 1, b: 2, }, vec![ Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(1), Token::EnumMapSep, Token::Str("b"), Token::Bool(false), Token::EnumMapEnd, ] ); assert_de_tokens( &DeserializeWithEnum::Struct { a: 1, b: 123, }, vec![ Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(1), Token::EnumMapSep, Token::Str("b"), Token::Bool(true), Token::EnumMapEnd, ] ); } #[test] fn test_missing_renamed_field_struct() { assert_de_tokens_error::( vec![ Token::StructStart("Superhero", Some(2)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructEnd, ], Error::MissingFieldError("a3"), ); assert_de_tokens_error::( vec![ Token::StructStart("SuperheroDe", Some(2)), Token::StructSep, Token::Str("a1"), Token::I32(1), Token::StructEnd, ], Error::MissingFieldError("a5"), ); } #[test] fn test_missing_renamed_field_enum() { assert_de_tokens_error::( vec![ Token::EnumMapStart("Superhero", "barry_allan", Some(1)), Token::EnumMapEnd, ], Error::MissingFieldError("b"), ); assert_de_tokens_error::>( vec![ Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)), Token::EnumMapSep, Token::Str("a"), Token::I8(0), Token::EnumMapEnd, ], Error::MissingFieldError("d"), ); }