diff --git a/CHANGELOG.md b/CHANGELOG.md index 4816a72f..c7aff3ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,6 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] -### Added -- Serde serializer can now be extended with custom struct encoding policy. ## 0.7.0 - 2015-08-24 ### Changed diff --git a/rmp-serde/CHANGELOG.md b/rmp-serde/CHANGELOG.md new file mode 100644 index 00000000..22868f2b --- /dev/null +++ b/rmp-serde/CHANGELOG.md @@ -0,0 +1,21 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased][unreleased] +### Changed +- Serializer can now be extended with custom struct encoding policy. +- Improved error types and its messages for serialization part. + - New error type introduced - UnknownLength. Returned on attempt to serialize struct, map or serquence with unknown + length (Serde allows this). + - The new type is returned if necessary. + +### Fixed +- Deserializer now properly works with enums. +- Options with default values (that can be initialized using unit marker) deserialization. + This fix also forbids the following Option deserialization cases: + - Option<()>. + - Option>. + It's impossible to properly deserialize the listed cases without explicit option marker in protocol. +- Serializer now properly serializes unit structs. + Previously it was serialized as a unit (nil), now there is just an empty array ([]). diff --git a/rmp-serde/src/decode.rs b/rmp-serde/src/decode.rs index b7359a05..05088e32 100644 --- a/rmp-serde/src/decode.rs +++ b/rmp-serde/src/decode.rs @@ -12,6 +12,7 @@ use rmp::decode::{ MarkerReadError, ReadError, ValueReadError, + read_array_size, read_numeric_data, read_str_data, read_marker, @@ -75,7 +76,7 @@ impl serde::de::Error for Error { serde::de::Type::Str => Error::TypeMismatch(Marker::Str32), serde::de::Type::String => Error::TypeMismatch(Marker::Str32), serde::de::Type::Unit => Error::TypeMismatch(Marker::Null), - serde::de::Type::Option => Error::TypeMismatch(Marker::True), + serde::de::Type::Option => Error::TypeMismatch(Marker::Null), serde::de::Type::Seq => Error::TypeMismatch(Marker::Array32), serde::de::Type::Map => Error::TypeMismatch(Marker::Map32), serde::de::Type::UnitStruct => Error::TypeMismatch(Marker::Null), @@ -150,6 +151,15 @@ impl From for Error { } } +impl From for Error { + fn from(err: serde::de::value::Error) -> Error { + match err { + serde::de::value::Error::SyntaxError => Error::Syntax("unknown".into()), + _ => Error::Uncategorized("unknown".into()), + } + } +} + pub type Result = result::Result; /// # Note @@ -160,6 +170,7 @@ pub type Result = result::Result; pub struct Deserializer { rd: R, buf: Vec, + decoding_option: bool, } impl Deserializer { @@ -168,6 +179,7 @@ impl Deserializer { Deserializer { rd: rd, buf: Vec::new(), + decoding_option: false, } } @@ -237,8 +249,16 @@ impl serde::Deserializer for Deserializer { fn visit(&mut self, mut visitor: V) -> Result where V: serde::de::Visitor { - match try!(read_marker(&mut self.rd)) { - Marker::Null => visitor.visit_unit(), + let marker = try!(read_marker(&mut self.rd)); + + match marker { + Marker::Null => { + if self.decoding_option { + visitor.visit_none() + } else { + visitor.visit_unit() + } + } Marker::True => visitor.visit_bool(true), Marker::False => visitor.visit_bool(false), Marker::FixPos(val) => visitor.visit_u8(val), @@ -307,14 +327,37 @@ impl serde::Deserializer for Deserializer { } /// We treat Value::Null as None. + /// + /// # Note + /// + /// Without using explicit option marker it's impossible to properly deserialize the following + /// specific cases: + /// - `Option<()>`. + /// - nested optionals, like `Option>`. fn visit_option(&mut self, mut visitor: V) -> Result where V: serde::de::Visitor, { // Primarily try to read optimisticly. - match visitor.visit_some(self) { + self.decoding_option = true; + let res = match visitor.visit_some(self) { Ok(val) => Ok(val), Err(Error::TypeMismatch(Marker::Null)) => visitor.visit_none(), Err(err) => Err(err) + }; + self.decoding_option = false; + + res + } + + fn visit_enum(&mut self, _enum: &str, _variants: &'static [&'static str], mut visitor: V) + -> Result + where V: serde::de::EnumVisitor + { + let len = try!(read_array_size(&mut self.rd)); + + match len { + 2 => visitor.visit(VariantVisitor::new(self)), + n => Err(Error::LengthMismatch(n as u32)), } } } @@ -385,3 +428,55 @@ impl<'a, R: Read + 'a> serde::de::MapVisitor for MapVisitor<'a, R> { } } } + +/// Default variant visitor. +/// +/// # Note +/// +/// We use default behaviour for new type, which decodes enums with a single value as a tuple. +pub struct VariantVisitor<'a, R: Read + 'a> { + de: &'a mut Deserializer, +} + +impl<'a, R: Read + 'a> VariantVisitor<'a, R> { + pub fn new(de: &'a mut Deserializer) -> VariantVisitor<'a, R> { + VariantVisitor { + de: de, + } + } +} + +impl<'a, R: Read> serde::de::VariantVisitor for VariantVisitor<'a, R> { + type Error = Error; + + // Resolves an internal variant type by integer id. + fn visit_variant(&mut self) -> Result + where V: serde::Deserialize + { + use serde::de::value::ValueDeserializer; + + let id: u32 = try!(serde::Deserialize::deserialize(self.de)); + + let mut de = (id as usize).into_deserializer(); + Ok(try!(V::deserialize(&mut de))) + } + + fn visit_unit(&mut self) -> Result<()> { + use serde::de::Deserialize; + + type T = (); + T::deserialize(self.de) + } + + fn visit_tuple(&mut self, len: usize, visitor: V) -> Result + where V: serde::de::Visitor, + { + serde::de::Deserializer::visit_tuple(self.de, len, visitor) + } + + fn visit_struct(&mut self, fields: &'static [&'static str], visitor: V) -> Result + where V: serde::de::Visitor, + { + serde::de::Deserializer::visit_tuple(self.de, fields.len(), visitor) + } +} diff --git a/rmp-serde/src/encode.rs b/rmp-serde/src/encode.rs index ad2801d1..f8bb675f 100644 --- a/rmp-serde/src/encode.rs +++ b/rmp-serde/src/encode.rs @@ -25,15 +25,25 @@ pub enum Error { /// Failed to write MessagePack'ed single-byte value into the write. InvalidFixedValueWrite(WriteError), InvalidValueWrite(ValueWriteError), + + /// Failed to serialize struct, sequence or map, because its length is unknown. + UnknownLength, } impl ::std::error::Error for Error { - fn description(&self) -> &str { "an error occurred while writing encoded value" } + fn description(&self) -> &str { + match *self { + Error::InvalidFixedValueWrite(..) => "invalid fixed value write", + Error::InvalidValueWrite(..) => "invalid value write", + Error::UnknownLength => "attempt to serialize struct, sequence or map with unknown length", + } + } fn cause(&self) -> Option<&::std::error::Error> { match *self { Error::InvalidFixedValueWrite(ref err) => Some(err), Error::InvalidValueWrite(ref err) => Some(err), + Error::UnknownLength => None, } } } @@ -229,7 +239,7 @@ impl<'a, W: VariantWriter> serde::Serializer for Serializer<'a, W> { let len = match visitor.len() { Some(len) => len, - None => panic!("do not know how to serialize a sequence with no length"), + None => return Err(Error::UnknownLength), }; // ... and its arguments length. @@ -266,7 +276,7 @@ impl<'a, W: VariantWriter> serde::Serializer for Serializer<'a, W> { { let len = match visitor.len() { Some(len) => len, - None => panic!("do not know how to serialize a sequence with no length"), + None => return Err(Error::UnknownLength), }; try!(write_array_len(&mut self.wr, len as u32)); @@ -287,7 +297,7 @@ impl<'a, W: VariantWriter> serde::Serializer for Serializer<'a, W> { { let len = match visitor.len() { Some(len) => len, - None => panic!("do not know how to serialize a map with no length"), + None => return Err(Error::UnknownLength), }; try!(write_map_len(&mut self.wr, len as u32)); @@ -305,12 +315,18 @@ impl<'a, W: VariantWriter> serde::Serializer for Serializer<'a, W> { value.serialize(self) } + fn visit_unit_struct(&mut self, _name: &'static str) -> Result<(), Error> { + try!(write_array_len(&mut self.wr, 0)); + + Ok(()) + } + fn visit_struct(&mut self, _name: &str, mut visitor: V) -> Result<(), Error> where V: serde::ser::MapVisitor, { let len = match visitor.len() { Some(len) => len, - None => panic!("do not know how to serialize a sequence with no length"), + None => return Err(Error::UnknownLength), }; try!(self.vw.write_struct_len(&mut self.wr, len as u32)); diff --git a/rmp-serde/tests/deserializer.rs b/rmp-serde/tests/de.rs similarity index 66% rename from rmp-serde/tests/deserializer.rs rename to rmp-serde/tests/de.rs index 89e31179..dded5314 100644 --- a/rmp-serde/tests/deserializer.rs +++ b/rmp-serde/tests/de.rs @@ -1,6 +1,3 @@ -#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))] -#![cfg_attr(feature = "serde_macros", plugin(serde_macros))] - extern crate serde; extern crate rmp; extern crate rmp_serde; @@ -235,36 +232,6 @@ fn fail_tuple_len_mismatch() { } } -#[cfg(feature = "serde_macros")] -#[test] -fn pass_tuple_struct() { - let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - struct Decoded(u32, u32); - - let mut deserializer = Deserializer::new(cur); - let actual: Decoded = Deserialize::deserialize(&mut deserializer).unwrap(); - - assert_eq!(Decoded(42, 100500), actual); -} - -#[cfg(feature = "serde_macros")] -#[test] -fn pass_struct() { - let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - struct Decoded { id: u32, value: u32 }; - - let mut deserializer = Deserializer::new(cur); - let actual: Decoded = Deserialize::deserialize(&mut deserializer).unwrap(); - - assert_eq!(Decoded { id: 42, value: 100500 }, actual); -} - #[test] fn pass_option_some() { let buf = [0x1f]; @@ -275,16 +242,6 @@ fn pass_option_some() { assert_eq!(Some(31), actual); } -#[test] -fn pass_option_some_null() { - let buf = [0xc0]; - let cur = Cursor::new(&buf[..]); - - let mut deserializer = Deserializer::new(cur); - let actual: Option<()> = Deserialize::deserialize(&mut deserializer).unwrap(); - assert_eq!(Some(()), actual); -} - #[test] fn pass_option_none() { let buf = [0xc0]; @@ -340,131 +297,6 @@ fn pass_map() { assert_eq!(expected, actual); } -#[cfg(feature = "serde_macros")] -#[test] -fn pass_struct_map() { - #[derive(Debug, PartialEq, Deserialize)] - struct Custom { - et: String, - le: u8, - shit: u8, - } - - let buf = [ - 0x83, // 3 (size) - 0xa2, 0x65, 0x74, // "et" - 0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila" - 0xa2, 0x6c, 0x65, // "le" - 0x00, // 0 - 0xa4, 0x73, 0x68, 0x69, 0x74, // "shit" - 0x01, // 1 - ]; - let cur = Cursor::new(&buf[..]); - - // it appears no special behavior is needed for deserializing structs encoded as maps - let mut deserializer = Deserializer::new(cur); - let actual: Custom = Deserialize::deserialize(&mut deserializer).unwrap(); - let voila = "voila".to_string(); // so the next line looks more funny - let expected = Custom { et: voila, le: 0, shit: 1 }; - - assert_eq!(expected, actual); -} - -#[cfg(feature = "serde_macros")] -#[test] -fn pass_enum() { - let buf = [0x92, 0x01, 0x90]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - enum Custom { - First, - Second, - } - - let mut deserializer = Deserializer::new(cur); - let actual: Custom = Deserialize::deserialize(&mut deserializer).unwrap(); - - assert_eq!(Custom::Second, actual); -} - -#[cfg(feature = "serde_macros")] -#[test] -fn pass_enum_variant_with_arg() { - let buf = [0x92, 0x01, 0x91, 0x2a]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - enum Custom { - First, - Second(u32), - } - - let mut deserializer = Deserializer::new(cur); - let actual: Custom = Deserialize::deserialize(&mut deserializer).unwrap(); - - assert_eq!(Custom::Second(42), actual); -} - -#[cfg(feature = "serde_macros")] -#[test] -fn fail_enum_sequence_mismatch() { - let buf = [0x93, 0x1, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - enum Custom { - First, - Second, - } - - let mut deserializer = Deserializer::new(cur); - let actual: Result = Deserialize::deserialize(&mut deserializer); - - match actual.err() { - Some(Error::Uncategorized(..)) => (), - other => panic!("unexpected result: {:?}", other) - } -} - -#[cfg(feature = "serde_macros")] -#[test] -fn fail_enum_overflow() { - let buf = [0x92, 0x01, 0x2a]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - enum Custom { - First, - } - - let mut deserializer = Deserializer::new(cur); - let actual: Result = Deserialize::deserialize(&mut deserializer); - - match actual.err() { - Some(Error::Uncategorized(..)) => (), - other => panic!("unexpected result: {:?}", other) - } -} - -#[cfg(feature = "serde_macros")] -#[test] -fn pass_struct_enum_with_arg() { - let buf = [0x92, 0x01, 0x91, 0x2a]; - let cur = Cursor::new(&buf[..]); - - #[derive(Debug, PartialEq, Deserialize)] - enum Custom { - First, - Second { id: u32 }, - } - - let mut deserializer = Deserializer::new(cur); - let actual: Custom = Deserialize::deserialize(&mut deserializer).unwrap(); - - assert_eq!(Custom::Second { id: 42 }, actual); -} - // TODO: Merge three of them. #[test] fn pass_bin8_into_bytebuf() { diff --git a/rmp-serde/tests/de_macro.rs b/rmp-serde/tests/de_macro.rs new file mode 100644 index 00000000..e4b04f71 --- /dev/null +++ b/rmp-serde/tests/de_macro.rs @@ -0,0 +1,259 @@ +#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))] +#![cfg_attr(feature = "serde_macros", plugin(serde_macros))] + +#![cfg(feature = "serde_macros")] + +extern crate serde; +extern crate rmp; +extern crate rmp_serde; + +use std::io::Cursor; +use std::result; + +use serde::Deserialize; + +use rmp_serde::Deserializer; +use rmp_serde::decode::Error; + +type Result = result::Result; + +#[test] +fn pass_tuple_struct() { + let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + struct Decoded(u32, u32); + + let mut de = Deserializer::new(cur); + let actual: Decoded = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Decoded(42, 100500), actual); +} + +#[test] +fn pass_struct() { + let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + struct Decoded { id: u32, value: u32 }; + + let mut de = Deserializer::new(cur); + let actual: Decoded = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Decoded { id: 42, value: 100500 }, actual); +} + +#[test] +fn pass_struct_map() { + #[derive(Debug, PartialEq, Deserialize)] + struct Struct { + et: String, + le: u8, + shit: u8, + } + + let buf = [ + 0x83, // 3 (size) + 0xa2, 0x65, 0x74, // "et" + 0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila" + 0xa2, 0x6c, 0x65, // "le" + 0x00, // 0 + 0xa4, 0x73, 0x68, 0x69, 0x74, // "shit" + 0x01, // 1 + ]; + let cur = Cursor::new(&buf[..]); + + // It appears no special behavior is needed for deserializing structs encoded as maps. + let mut de = Deserializer::new(cur); + let actual: Struct = Deserialize::deserialize(&mut de).unwrap(); + let expected = Struct { et: "voila".into(), le: 0, shit: 1 }; + + assert_eq!(expected, actual); +} + +#[test] +fn pass_enum() { + // We expect enums to be endoded as [id, [...]] + + let buf = [0x92, 0x01, 0x90]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A, + B, + } + + let mut de = Deserializer::new(cur); + let actual: Enum = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Enum::B, actual); + assert_eq!(3, de.get_ref().position()); +} + +#[test] +fn pass_tuple_enum_with_arg() { + // The encoded bytearray is: [1, [42]]. + let buf = [0x92, 0x01, 0x91, 0x2a]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A, + B(u32), + } + + let mut de = Deserializer::new(cur); + let actual: Enum = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Enum::B(42), actual); + assert_eq!(4, de.get_ref().position()) +} + +#[test] +fn pass_tuple_enum_with_args() { + // The encoded bytearray is: [1, [42, 58]]. + let buf = [0x92, 0x01, 0x92, 0x2a, 0x3a]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A, + B(u32, u32), + } + + let mut de = Deserializer::new(cur); + let actual: Enum = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Enum::B(42, 58), actual); + assert_eq!(5, de.get_ref().position()) +} + +#[test] +fn fail_enum_sequence_mismatch() { + // The encoded bytearray is: [1, 2, 100500]. + let buf = [0x93, 0x1, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A, + B, + } + + let mut de = Deserializer::new(cur); + let actual: Result = Deserialize::deserialize(&mut de); + + match actual.err().unwrap() { + Error::LengthMismatch(3) => (), + other => panic!("unexpected result: {:?}", other) + } +} + +#[test] +fn fail_enum_overflow() { + // The encoded bytearray is: [1, [42]]. + let buf = [0x92, 0x01, 0x2a]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + // TODO: Rename to Enum: A, B, C, ... + enum Enum { + A, + } + + let mut de = Deserializer::new(cur); + let actual: Result = Deserialize::deserialize(&mut de); + + match actual.err().unwrap() { + Error::Syntax(..) => (), + other => panic!("unexpected result: {:?}", other) + } +} + +#[test] +fn pass_struct_enum_with_arg() { + // The encoded bytearray is: [1, [42]]. + let buf = [0x92, 0x01, 0x91, 0x2a]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A, + B { id: u32 }, + } + + let mut de = Deserializer::new(cur); + let actual: Enum = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Enum::B { id: 42 }, actual); + assert_eq!(4, de.get_ref().position()) +} + +#[test] +fn pass_enum_with_nested_struct() { + // The encoded bytearray is: [0, [['le message']]]. + let buf = [0x92, 0x0, 0x91, 0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + struct Nested(String); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A(Nested), + B, + } + + let mut de = Deserializer::new(cur); + let actual: Enum = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Enum::A(Nested("le message".into())), actual); + assert_eq!(buf.len() as u64, de.get_ref().position()) +} + +#[test] +fn pass_enum_custom_policy() { + use std::io::Read; + use rmp_serde::decode::VariantVisitor; + + // We expect enums to be endoded as id, [...] (without wrapping tuple). + + let buf = [0x01, 0x90]; + let cur = Cursor::new(&buf[..]); + + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + A, + B, + } + + struct CustomDeserializer { + inner: Deserializer, + } + + impl serde::Deserializer for CustomDeserializer { + type Error = Error; + + fn visit(&mut self, visitor: V) -> Result + where V: serde::de::Visitor + { + self.inner.visit(visitor) + } + + fn visit_enum(&mut self, _enum: &str, _variants: &'static [&'static str], mut visitor: V) + -> Result + where V: serde::de::EnumVisitor + { + visitor.visit(VariantVisitor::new(&mut self.inner)) + } + } + + let mut de = CustomDeserializer { inner: Deserializer::new(cur) }; + let actual: Enum = Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(Enum::B, actual); + assert_eq!(2, de.inner.get_ref().position()); +} diff --git a/rmp-serde/tests/round.rs b/rmp-serde/tests/round.rs new file mode 100644 index 00000000..79db8212 --- /dev/null +++ b/rmp-serde/tests/round.rs @@ -0,0 +1,72 @@ +#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))] +#![cfg_attr(feature = "serde_macros", plugin(serde_macros))] + +#![cfg(feature = "serde_macros")] + +extern crate serde; +extern crate rmp_serde; + +#[test] +fn round_trip_option() { + use std::io::Cursor; + use serde::Serialize; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Foo { + v: Option>, + } + + let expected = Foo { v: None }; + + let mut data = vec![]; + expected.serialize(&mut rmp_serde::encode::Serializer::new(&mut data)).unwrap(); + + let mut de = rmp_serde::decode::Deserializer::new(Cursor::new(&data[..])); + let actual: Foo = serde::Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn round_trip_cow() { + use std::borrow::Cow; + use std::io::Cursor; + use serde::Serialize; + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + struct Foo<'a> { + v: Cow<'a, [u8]>, + } + + let expected = Foo { v : Cow::Borrowed(&[]) }; + + let mut data = vec![]; + expected.serialize(&mut rmp_serde::encode::Serializer::new(&mut data)).unwrap(); + + let mut de = rmp_serde::decode::Deserializer::new(Cursor::new(&data[..])); + let actual: Foo = serde::Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(expected, actual); +} + +#[test] +fn round_trip_option_cow() { + use std::borrow::Cow; + use std::io::Cursor; + use serde::Serialize; + + #[derive(Serialize, Deserialize, Debug, PartialEq)] + struct Foo<'a> { + v: Option>, + } + + let expected = Foo { v : None }; + + let mut data = vec![]; + expected.serialize(&mut rmp_serde::encode::Serializer::new(&mut data)).unwrap(); + + let mut de = rmp_serde::decode::Deserializer::new(Cursor::new(&data[..])); + let actual: Foo = serde::Deserialize::deserialize(&mut de).unwrap(); + + assert_eq!(expected, actual); +} diff --git a/rmp-serde/tests/serializer.rs b/rmp-serde/tests/se.rs similarity index 68% rename from rmp-serde/tests/serializer.rs rename to rmp-serde/tests/se.rs index 65cc1279..dac8b283 100644 --- a/rmp-serde/tests/serializer.rs +++ b/rmp-serde/tests/se.rs @@ -1,6 +1,3 @@ -#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))] -#![cfg_attr(feature = "serde_macros", plugin(serde_macros))] - extern crate serde; extern crate rmp; extern crate rmp_serde; @@ -193,20 +190,6 @@ fn pass_string() { assert_eq!([0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65], buf); } -#[cfg(feature = "serde_macros")] -#[test] -fn pass_struct() { - let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - - #[derive(Serialize)] - struct Decoded { id: u32, value: u32 } - - let val = Decoded { id: 42, value: 100500 }; - val.serialize(&mut Serializer::new(&mut &mut buf[..])).ok().unwrap(); - - assert_eq!([0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94], buf); -} - #[test] fn pass_tuple() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -268,96 +251,23 @@ fn pass_map() { assert_eq!(out, buf); } -#[cfg(feature = "serde_macros")] #[test] -fn pass_struct_map() { - use std::io::Write; - use rmp::Marker; - use rmp::encode::{ValueWriteError, write_map_len, write_str}; - use rmp_serde::encode::VariantWriter; - - struct StructMapWriter; - - impl VariantWriter for StructMapWriter { - fn write_struct_len(&self, wr: &mut W, len: u32) -> Result - where W: Write - { - write_map_len(wr, len) - } - - fn write_field_name(&self, wr: &mut W, _key: &str) -> Result<(), ValueWriteError> - where W: Write - { - write_str(wr, _key) - } - } - - #[derive(Debug, PartialEq, Serialize)] - struct Custom<'a> { - et: &'a str, - le: u8, - shit: u8, - } +fn pass_empty_map() { + use std::collections::BTreeMap; - let mut buf = [0x00; 20]; + let mut buf = vec![]; - let val = Custom { et: "voila", le: 0, shit: 1 }; - val.serialize(&mut Serializer::with(&mut &mut buf[..], StructMapWriter)).ok().unwrap(); + let val: BTreeMap = BTreeMap::new(); + val.serialize(&mut Serializer::new(&mut buf)).ok().unwrap(); - let out = [ - 0x83, // 3 (size) - 0xa2, 0x65, 0x74, // "et" - 0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila" - 0xa2, 0x6c, 0x65, // "le" - 0x00, // 0 - 0xa4, 0x73, 0x68, 0x69, 0x74, // "shit" - 0x01, // 1 + let out = vec![ + 0x80, // (size: 0) ]; assert_eq!(out, buf); } -#[cfg(feature = "serde_macros")] -#[test] -fn pass_enum() { - // We encode enum types as [id, [args...]]. - - #[allow(unused)] - #[derive(Debug, PartialEq, Serialize)] - enum Custom { - First, - Second, - } - - let mut buf = [0x00; 3]; - - let val = Custom::Second; - val.serialize(&mut Serializer::new(&mut &mut buf[..])).ok().unwrap(); - - let out = [0x92, 0x01, 0x90]; - assert_eq!(out, buf); -} - -#[cfg(feature = "serde_macros")] -#[test] -fn pass_enum_variant_with_arg() { - #[allow(unused)] - #[derive(Debug, PartialEq, Serialize)] - enum Custom { - First, - Second(u32), - } - - let mut buf = [0x00; 4]; - - let val = Custom::Second(42); - val.serialize(&mut Serializer::new(&mut &mut buf[..])).ok().unwrap(); - - let out = [0x92, 0x01, 0x91, 0x2a]; - assert_eq!(out, buf); -} - #[test] -fn pass_encodong_struct_into_vec() { +fn pass_encoding_struct_into_vec() { let val = (42u8, "the Answer"); let mut buf: Vec = Vec::new(); @@ -367,23 +277,6 @@ fn pass_encodong_struct_into_vec() { assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf); } -#[cfg(feature = "serde_macros")] -#[test] -fn encode_struct_with_string_using_vec() { - #[derive(Debug, PartialEq, Serialize)] - struct Custom { - data: String, - } - - let mut buf = Vec::new(); - - let val = Custom { data: "le message".to_string() }; - val.serialize(&mut Serializer::new(&mut buf)).ok().unwrap(); - - let out = vec![0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; - assert_eq!(out, buf); -} - #[test] fn pass_bin() { use serde::bytes::Bytes; diff --git a/rmp-serde/tests/se_macro.rs b/rmp-serde/tests/se_macro.rs new file mode 100644 index 00000000..7adbd127 --- /dev/null +++ b/rmp-serde/tests/se_macro.rs @@ -0,0 +1,140 @@ +#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))] +#![cfg_attr(feature = "serde_macros", plugin(serde_macros))] + +#![cfg(feature = "serde_macros")] + +extern crate serde; +extern crate rmp; +extern crate rmp_serde; + +use serde::Serialize; +use rmp_serde::Serializer; +use rmp_serde::encode::Error; + +#[test] +fn pass_struct() { + let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + + #[derive(Serialize)] + struct Decoded { id: u32, value: u32 } + + let val = Decoded { id: 42, value: 100500 }; + val.serialize(&mut Serializer::new(&mut &mut buf[..])).ok().unwrap(); + + assert_eq!([0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94], buf); +} + +#[test] +fn pass_empty_struct() { + // Must be encoded as []. + let mut buf = vec![]; + + #[derive(Serialize)] + struct Struct; + + let val = Struct; + val.serialize(&mut Serializer::new(&mut buf)).ok().unwrap(); + + assert_eq!(vec![0x90], buf); +} + +#[test] +fn pass_struct_map() { + use std::io::Write; + use rmp::Marker; + use rmp::encode::{ValueWriteError, write_map_len, write_str}; + use rmp_serde::encode::VariantWriter; + + struct StructMapWriter; + + impl VariantWriter for StructMapWriter { + fn write_struct_len(&self, wr: &mut W, len: u32) -> Result + where W: Write + { + write_map_len(wr, len) + } + + fn write_field_name(&self, wr: &mut W, _key: &str) -> Result<(), ValueWriteError> + where W: Write + { + write_str(wr, _key) + } + } + + #[derive(Debug, PartialEq, Serialize)] + struct Custom<'a> { + et: &'a str, + le: u8, + shit: u8, + } + + let mut buf = [0x00; 20]; + + let val = Custom { et: "voila", le: 0, shit: 1 }; + val.serialize(&mut Serializer::with(&mut &mut buf[..], StructMapWriter)).ok().unwrap(); + + let out = [ + 0x83, // 3 (size) + 0xa2, 0x65, 0x74, // "et" + 0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila" + 0xa2, 0x6c, 0x65, // "le" + 0x00, // 0 + 0xa4, 0x73, 0x68, 0x69, 0x74, // "shit" + 0x01, // 1 + ]; + assert_eq!(out, buf); +} + +#[test] +fn pass_enum() { + // We encode enum types as [id, [args...]]. + + #[allow(unused)] + #[derive(Debug, PartialEq, Serialize)] + enum Custom { + First, + Second, + } + + let mut buf = [0x00; 3]; + + let val = Custom::Second; + val.serialize(&mut Serializer::new(&mut &mut buf[..])).ok().unwrap(); + + let out = [0x92, 0x01, 0x90]; + assert_eq!(out, buf); +} + +#[test] +fn pass_tuple_enum_with_arg() { + #[allow(unused)] + #[derive(Debug, PartialEq, Serialize)] + enum Custom { + First, + Second(u32), + } + + let mut buf = [0x00; 4]; + + let val = Custom::Second(42); + val.serialize(&mut Serializer::new(&mut &mut buf[..])).ok().unwrap(); + + let out = [0x92, 0x01, 0x91, 0x2a]; + assert_eq!(out, buf); +} + +#[test] +fn encode_struct_with_string_using_vec() { + #[derive(Debug, PartialEq, Serialize)] + struct Custom { + data: String, + } + + let mut buf = Vec::new(); + + let val = Custom { data: "le message".to_string() }; + val.serialize(&mut Serializer::new(&mut buf)).ok().unwrap(); + + let out = vec![0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; + assert_eq!(out, buf); +}