From fb7ba225d197f4a54771ac528abee69e89155b50 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 23 Aug 2016 16:23:44 -0400 Subject: [PATCH 001/111] Add constructors for Bytes and ByteBuf This commit adds `Bytes::new(&[u8])` and `ByteBuf::from>>(T)`. --- serde/src/bytes.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs index 67f8ce85..12e42e75 100644 --- a/serde/src/bytes.rs +++ b/serde/src/bytes.rs @@ -19,6 +19,15 @@ pub struct Bytes<'a> { bytes: &'a [u8], } +impl<'a> Bytes<'a> { + /// Wrap an existing `&[u8]`. + pub fn new(bytes: &'a [u8]) -> Self { + Bytes { + bytes: bytes, + } + } +} + impl<'a> fmt::Debug for Bytes<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(f.write_str("b\"")); @@ -101,6 +110,13 @@ mod bytebuf { bytes: Vec::with_capacity(cap) } } + + /// Wrap existing bytes in a `ByteBuf`. + pub fn from>>(bytes: T) -> Self { + ByteBuf { + bytes: bytes.into(), + } + } } impl fmt::Debug for ByteBuf { From 2a2891d54b9c0bf32eb3d90debb331436eeaefec Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 24 Aug 2016 00:10:23 -0400 Subject: [PATCH 002/111] Expose forward_to_deserialize macro --- serde/src/de/mod.rs | 65 ------------- serde/src/de/value.rs | 207 +++++++++--------------------------------- serde/src/lib.rs | 3 + serde/src/macros.rs | 132 +++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 227 deletions(-) create mode 100644 serde/src/macros.rs diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 571c73b7..210b36b0 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -11,71 +11,6 @@ use collections::{String, Vec}; use core::fmt; /////////////////////////////////////////////////////////////////////////////// -/// Macro helper to not have to re-implement all the defaulted methods. -/// Every given method ignores all arguments and forwards to `deserialize`. -/// Note that `deserialize_enum` simply returns an `Error::invalid_type`. -macro_rules! de_forward_to_deserialize { - ($($func:ident),*) => { - $(de_forward_to_deserialize!{func: $func})* - }; - (func: deserialize_unit_struct) => { - de_forward_to_deserialize!{named: deserialize_unit_struct} - }; - (func: deserialize_newtype_struct) => { - de_forward_to_deserialize!{named: deserialize_newtype_struct} - }; - (func: deserialize_tuple) => { - de_forward_to_deserialize!{tup_fn: deserialize_tuple} - }; - (func: deserialize_seq_fixed_size) => { - de_forward_to_deserialize!{tup_fn: deserialize_seq_fixed_size} - }; - (func: deserialize_tuple_struct) => { - #[inline] - fn deserialize_tuple_struct<__V>(&mut self, _: &str, _: usize, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor { - self.deserialize(visitor) - } - }; - (func: deserialize_struct) => { - #[inline] - fn deserialize_struct<__V>(&mut self, _: &str, _: &[&str], visitor: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor { - self.deserialize(visitor) - } - }; - (func: deserialize_enum) => { - #[inline] - fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::EnumVisitor { - Err($crate::de::Error::invalid_type($crate::de::Type::Enum)) - } - }; - (named: $func:ident) => { - #[inline] - fn $func<__V>(&mut self, _: &str, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor { - self.deserialize(visitor) - } - }; - (tup_fn: $func: ident) => { - #[inline] - fn $func<__V>(&mut self, _: usize, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor { - self.deserialize(visitor) - } - }; - (func: $func:ident) => { - #[inline] - fn $func<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor { - self.deserialize(visitor) - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -// modules come after macros pub mod impls; pub mod value; diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index bf3e0631..6f9e7d4b 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -178,20 +178,10 @@ impl de::Deserializer for UnitDeserializer { type Error = E; - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } fn deserialize(&mut self, mut visitor: V) -> Result @@ -229,21 +219,11 @@ macro_rules! primitive_deserializer { { type Error = E; - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit option seq seq_fixed_size bytes map unit_struct + newtype_struct tuple_struct struct struct_field tuple enum + ignored_any } fn deserialize(&mut self, mut visitor: V) -> Result @@ -311,20 +291,10 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E> visitor.visit(self) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple ignored_any } } @@ -408,20 +378,10 @@ impl de::Deserializer for StringDeserializer visitor.visit(self) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple ignored_any } } @@ -507,20 +467,10 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E> visitor.visit(self) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple ignored_any } } @@ -599,21 +549,10 @@ impl de::Deserializer for SeqDeserializer visitor.visit_seq(self) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } } @@ -722,21 +661,10 @@ impl de::Deserializer for SeqVisitorDeserializer visitor.visit_seq(&mut self.visitor) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } } @@ -797,21 +725,10 @@ impl de::Deserializer for MapDeserializer visitor.visit_map(self) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } } @@ -928,21 +845,10 @@ impl de::Deserializer for MapVisitorDeserializer visitor.visit_map(&mut self.visitor) } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } } @@ -975,25 +881,13 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E> } } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } } - /////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "collections"))] @@ -1026,20 +920,9 @@ impl de::Deserializer for ByteBufDeserializer } } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option seq seq_fixed_size bytes map unit_struct newtype_struct + tuple_struct struct struct_field tuple enum ignored_any } } diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 54dcc120..78a0531e 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -45,6 +45,9 @@ macro_rules! format { ($s:expr, $($rest:tt)*) => ($s) } +#[macro_use] +mod macros; + pub mod bytes; pub mod de; #[cfg(feature = "std")] diff --git a/serde/src/macros.rs b/serde/src/macros.rs new file mode 100644 index 00000000..a997a148 --- /dev/null +++ b/serde/src/macros.rs @@ -0,0 +1,132 @@ +/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`. +/// Every given method ignores all arguments and forwards to `deserialize`. +/// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a +/// better approach is tracked in [serde-rs/serde#521][1]. +/// +/// ```rust,ignore +/// impl Deserializer for MyDeserializer { +/// fn deserialize(&mut self, visitor: V) -> Result +/// where V: Visitor +/// { +/// /* ... */ +/// } +/// +/// forward_to_deserialize! { +/// bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string +/// unit option seq seq_fixed_size bytes map unit_struct newtype_struct +/// tuple_struct struct struct_field tuple enum ignored_any +/// } +/// } +/// ``` +/// +/// [1]: https://github.com/serde-rs/serde/issues/521 +#[macro_export] +macro_rules! forward_to_deserialize { + (@func bool) => { + forward_to_deserialize!{@forward deserialize_bool()} + }; + (@func usize) => { + forward_to_deserialize!{@forward deserialize_usize()} + }; + (@func u8) => { + forward_to_deserialize!{@forward deserialize_u8()} + }; + (@func u16) => { + forward_to_deserialize!{@forward deserialize_u16()} + }; + (@func u32) => { + forward_to_deserialize!{@forward deserialize_u32()} + }; + (@func u64) => { + forward_to_deserialize!{@forward deserialize_u64()} + }; + (@func isize) => { + forward_to_deserialize!{@forward deserialize_isize()} + }; + (@func i8) => { + forward_to_deserialize!{@forward deserialize_i8()} + }; + (@func i16) => { + forward_to_deserialize!{@forward deserialize_i16()} + }; + (@func i32) => { + forward_to_deserialize!{@forward deserialize_i32()} + }; + (@func i64) => { + forward_to_deserialize!{@forward deserialize_i64()} + }; + (@func f32) => { + forward_to_deserialize!{@forward deserialize_f32()} + }; + (@func f64) => { + forward_to_deserialize!{@forward deserialize_f64()} + }; + (@func char) => { + forward_to_deserialize!{@forward deserialize_char()} + }; + (@func str) => { + forward_to_deserialize!{@forward deserialize_str()} + }; + (@func string) => { + forward_to_deserialize!{@forward deserialize_string()} + }; + (@func unit) => { + forward_to_deserialize!{@forward deserialize_unit()} + }; + (@func option) => { + forward_to_deserialize!{@forward deserialize_option()} + }; + (@func seq) => { + forward_to_deserialize!{@forward deserialize_seq()} + }; + (@func seq_fixed_size) => { + forward_to_deserialize!{@forward deserialize_seq_fixed_size(usize)} + }; + (@func bytes) => { + forward_to_deserialize!{@forward deserialize_bytes()} + }; + (@func map) => { + forward_to_deserialize!{@forward deserialize_map()} + }; + (@func unit_struct) => { + forward_to_deserialize!{@forward deserialize_unit_struct(&'static str)} + }; + (@func newtype_struct) => { + forward_to_deserialize!{@forward deserialize_newtype_struct(&'static str)} + }; + (@func tuple_struct) => { + forward_to_deserialize!{@forward deserialize_tuple_struct(&'static str, usize)} + }; + (@func struct) => { + forward_to_deserialize!{@forward deserialize_struct(&'static str, &'static [&'static str])} + }; + (@func struct_field) => { + forward_to_deserialize!{@forward deserialize_struct_field()} + }; + (@func tuple) => { + forward_to_deserialize!{@forward deserialize_tuple(usize)} + }; + (@func enum) => { + #[inline] + fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error> + where __V: $crate::de::EnumVisitor + { + Err($crate::de::Error::invalid_type($crate::de::Type::Enum)) + } + }; + (@func ignored_any) => { + forward_to_deserialize!{@forward deserialize_ignored_any()} + }; + (@forward $func:ident($($arg:ty),*)) => { + #[inline] + fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error> + where __V: $crate::de::Visitor + { + self.deserialize(visitor) + } + }; + + ($($func:ident)*) => { + $(forward_to_deserialize!{@func $func})* + }; +} From e9b04de9a5d4691ea1cb68f741ebdedf9af2e70d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 25 Aug 2016 09:37:16 -0400 Subject: [PATCH 003/111] Impl SeqVisitor for MapDeserializer --- serde/src/de/value.rs | 142 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index bf3e0631..4fcbd000 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -781,6 +781,15 @@ impl MapDeserializer marker: PhantomData, } } + + fn next(&mut self) -> Option<(K, V)> { + self.iter.next().map(|(k, v)| { + if let Some(len) = self.len.as_mut() { + *len -= 1; + } + (k, v) + }) + } } impl de::Deserializer for MapDeserializer @@ -826,14 +835,11 @@ impl de::MapVisitor for MapDeserializer fn visit_key(&mut self) -> Result, Self::Error> where T: de::Deserialize, { - match self.iter.next() { + match self.next() { Some((key, value)) => { - if let Some(len) = self.len.as_mut() { - *len -= 1; - } self.value = Some(value); let mut de = key.into_deserializer(); - Ok(Some(try!(de::Deserialize::deserialize(&mut de)))) + de::Deserialize::deserialize(&mut de).map(Some) } None => Ok(None), } @@ -867,6 +873,132 @@ impl de::MapVisitor for MapDeserializer } } +impl de::SeqVisitor for MapDeserializer + where I: Iterator, + K: ValueDeserializer, + V: ValueDeserializer, + E: de::Error, +{ + type Error = E; + + fn visit(&mut self) -> Result, Self::Error> + where T: de::Deserialize, + { + match self.next() { + Some(kv) => { + let mut de = PairDeserializer(Some(kv), PhantomData); + de::Deserialize::deserialize(&mut de).map(Some) + } + None => Ok(None), + } + } + + fn end(&mut self) -> Result<(), Self::Error> { + de::MapVisitor::end(self) + } + + fn size_hint(&self) -> (usize, Option) { + de::MapVisitor::size_hint(self) + } +} + +// Used in the `impl SeqVisitor for MapDeserializer` to visit the map as a +// sequence of pairs. +struct PairDeserializer(Option<(A, B)>, PhantomData); + +impl de::Deserializer for PairDeserializer + where A: ValueDeserializer, + B: ValueDeserializer, + E: de::Error +{ + type Error = E; + + de_forward_to_deserialize!{ + deserialize_bool, + deserialize_f64, deserialize_f32, + deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, + deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, + deserialize_char, deserialize_str, deserialize_string, + deserialize_ignored_any, + deserialize_bytes, + deserialize_unit_struct, deserialize_unit, deserialize_option, + deserialize_map, deserialize_newtype_struct, deserialize_struct_field, + deserialize_tuple, + deserialize_enum, + deserialize_struct, deserialize_tuple_struct + } + + fn deserialize(&mut self, visitor: V) -> Result + where V: de::Visitor, + { + self.deserialize_seq(visitor) + } + + fn deserialize_seq(&mut self, mut visitor: V) -> Result + where V: de::Visitor, + { + match self.0.take() { + Some((k, v)) => { + visitor.visit_seq(PairVisitor(Some(k), Some(v), PhantomData)) + } + None => Err(de::Error::end_of_stream()), + } + } + + fn deserialize_seq_fixed_size(&mut self, len: usize, visitor: V) -> Result + where V: de::Visitor, + { + if len == 2 { + self.deserialize_seq(visitor) + } else { + Err(de::Error::invalid_length(len)) + } + } +} + +struct PairVisitor(Option, Option, PhantomData); + +impl de::SeqVisitor for PairVisitor + where A: ValueDeserializer, + B: ValueDeserializer, + E: de::Error, +{ + type Error = E; + + fn visit(&mut self) -> Result, Self::Error> + where T: de::Deserialize, + { + if let Some(k) = self.0.take() { + let mut de = k.into_deserializer(); + de::Deserialize::deserialize(&mut de).map(Some) + } else if let Some(v) = self.1.take() { + let mut de = v.into_deserializer(); + de::Deserialize::deserialize(&mut de).map(Some) + } else { + Ok(None) + } + } + + fn end(&mut self) -> Result<(), Self::Error> { + if self.1.is_none() { + Ok(()) + } else { + Err(de::Error::invalid_length(self.size_hint().0)) + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = if self.0.is_some() { + 2 + } else if self.1.is_some() { + 1 + } else { + 0 + }; + (len, Some(len)) + } +} + /////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "collections"))] From 278e8eb720b7fe3bf6e3afe6d79e331d1607701d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 25 Aug 2016 10:45:25 -0400 Subject: [PATCH 004/111] Add deserialize_seq methods to MapDeserializer --- serde/src/de/value.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 4fcbd000..5cb17318 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -806,6 +806,22 @@ impl de::Deserializer for MapDeserializer visitor.visit_map(self) } + fn deserialize_seq(&mut self, mut visitor: V_) -> Result + where V_: de::Visitor, + { + visitor.visit_seq(self) + } + + fn deserialize_seq_fixed_size(&mut self, len: usize, mut visitor: V_) -> Result + where V_: de::Visitor, + { + match self.len { + Some(map_len) if map_len == len => visitor.visit_seq(self), + Some(_) => Err(de::Error::invalid_length(len)), + None => visitor.visit_seq(self), + } + } + de_forward_to_deserialize!{ deserialize_bool, deserialize_f64, deserialize_f32, @@ -815,7 +831,6 @@ impl de::Deserializer for MapDeserializer deserialize_ignored_any, deserialize_bytes, deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, deserialize_map, deserialize_newtype_struct, deserialize_struct_field, deserialize_tuple, deserialize_enum, From f3d566af0926333d428ad16c7b70ecdeb72a1d3e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Aug 2016 08:37:55 -0700 Subject: [PATCH 005/111] Remove clippy shield --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1cad02db..6e6be364 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) [![Clippy Linting Result](https://clippy.bashy.io/github/serde-rs/serde/master/badge.svg)](https://clippy.bashy.io/github/serde-rs/serde/master/log) +# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** From 7014c105b46e0b9cd01a3b899468d8e81c738a39 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Aug 2016 08:39:53 -0700 Subject: [PATCH 006/111] Remove coverage shield --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e6be364..9a8839d5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) +# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** From d914fdf67b175b95168f163727578ac0b8d6883b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Aug 2016 22:19:17 -0700 Subject: [PATCH 007/111] Macros 1.1 --- serde_codegen/src/lib.rs | 90 +++++++++++++++++++++++----------------- serde_derive/Cargo.toml | 18 ++++++++ serde_derive/src/lib.rs | 20 +++++++++ tmp_test/Cargo.toml | 9 ++++ tmp_test/build.sh | 32 ++++++++++++++ tmp_test/src/main.rs | 16 +++++++ 6 files changed, 148 insertions(+), 37 deletions(-) create mode 100644 serde_derive/Cargo.toml create mode 100644 serde_derive/src/lib.rs create mode 100644 tmp_test/Cargo.toml create mode 100755 tmp_test/build.sh create mode 100644 tmp_test/src/main.rs diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index fcdc6f4e..55318af6 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -35,6 +35,58 @@ include!(concat!(env!("OUT_DIR"), "/lib.rs")); #[cfg(not(feature = "with-syntex"))] include!("lib.rs.in"); +#[cfg(feature = "with-syntex")] +fn syntex_registry() -> syntex::Registry { + use syntax::{ast, fold}; + + /// Strip the serde attributes from the crate. + #[cfg(feature = "with-syntex")] + fn strip_attributes(krate: ast::Crate) -> ast::Crate { + /// Helper folder that strips the serde attributes after the extensions have been expanded. + struct StripAttributeFolder; + + impl fold::Folder for StripAttributeFolder { + fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { + match attr.node.value.node { + ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; } + _ => {} + } + + Some(attr) + } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } + } + + fold::Folder::fold_crate(&mut StripAttributeFolder, krate) + } + + let mut reg = syntex::Registry::new(); + + reg.add_attr("feature(custom_derive)"); + reg.add_attr("feature(custom_attribute)"); + + reg.add_decorator("derive_Serialize", ser::expand_derive_serialize); + reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize); + + reg.add_post_expansion_pass(strip_attributes); + + reg +} + +#[cfg(feature = "with-syntex")] +pub fn expand_str(src: &str) -> Result { + let src = src.to_owned(); + + let expand_thread = move || { + syntex_registry().expand_str("", "", &src) + }; + + syntex::with_extra_stack(expand_thread) +} + #[cfg(feature = "with-syntex")] pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> where S: AsRef, @@ -44,43 +96,7 @@ pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> let dst = dst.as_ref().to_owned(); let expand_thread = move || { - use syntax::{ast, fold}; - - /// Strip the serde attributes from the crate. - #[cfg(feature = "with-syntex")] - fn strip_attributes(krate: ast::Crate) -> ast::Crate { - /// Helper folder that strips the serde attributes after the extensions have been expanded. - struct StripAttributeFolder; - - impl fold::Folder for StripAttributeFolder { - fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { - match attr.node.value.node { - ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; } - _ => {} - } - - Some(attr) - } - - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } - } - - fold::Folder::fold_crate(&mut StripAttributeFolder, krate) - } - - let mut reg = syntex::Registry::new(); - - reg.add_attr("feature(custom_derive)"); - reg.add_attr("feature(custom_attribute)"); - - reg.add_decorator("derive_Serialize", ser::expand_derive_serialize); - reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize); - - reg.add_post_expansion_pass(strip_attributes); - - reg.expand("", src, dst) + syntex_registry().expand("", src, dst) }; syntex::with_extra_stack(expand_thread) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml new file mode 100644 index 00000000..8702b267 --- /dev/null +++ b/serde_derive/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "serde_derive" +version = "0.8.4" +authors = ["Erick Tryzelaar "] +license = "MIT/Apache-2.0" +description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" +homepage = "https://serde.rs" +repository = "https://github.com/serde-rs/serde" +documentation = "https://serde.rs/codegen.html" +keywords = ["serde", "serialization"] +include = ["Cargo.toml", "src/**/*.rs"] + +[lib] +name = "serde_derive" +rustc-macro = true + +[dependencies] +serde_codegen = { version = "=0.8.4", path = "../serde_codegen" } diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs new file mode 100644 index 00000000..d0cc0ef9 --- /dev/null +++ b/serde_derive/src/lib.rs @@ -0,0 +1,20 @@ +#![feature(rustc_macro)] + +extern crate rustc_macro; +extern crate serde_codegen; + +use rustc_macro::TokenStream; + +#[rustc_macro_derive(Serialize)] +pub fn derive_serialize(input: TokenStream) -> TokenStream { + let item = format!("#[derive(Serialize)]\n{}", input); + let expanded = serde_codegen::expand_str(&item).unwrap(); + expanded.parse().unwrap() +} + +#[rustc_macro_derive(Deserialize)] +pub fn derive_deserialize(input: TokenStream) -> TokenStream { + let item = format!("#[derive(Deserialize)]\n{}", input); + let expanded = serde_codegen::expand_str(&item).unwrap(); + expanded.parse().unwrap() +} diff --git a/tmp_test/Cargo.toml b/tmp_test/Cargo.toml new file mode 100644 index 00000000..ba3866cb --- /dev/null +++ b/tmp_test/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "tmp-test" +version = "0.1.0" +authors = ["David Tolnay "] + +[dependencies] +serde = "0.8" +serde_derive = { path = "../serde_derive" } +serde_json = "0.8" diff --git a/tmp_test/build.sh b/tmp_test/build.sh new file mode 100755 index 00000000..a2ed781b --- /dev/null +++ b/tmp_test/build.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -xeuo pipefail + +DIR=$(cd "$(dirname "$0")" && pwd) + +export RUSTC=${RUSTC:-$HOME/.local/bin/rustc} + +cargo build || true + +"$RUSTC" \ + "$DIR"/../serde_derive/src/lib.rs \ + --crate-name serde_derive \ + --crate-type rustc-macro \ + -C prefer-dynamic \ + -g \ + --out-dir "$DIR"/target/debug/deps \ + --emit=dep-info,link \ + -L dependency="$DIR"/target/debug/deps \ + --extern serde_codegen="$DIR"/target/debug/deps/libserde_codegen.rlib + +"$RUSTC" \ + src/main.rs \ + --crate-name tmp_test \ + --crate-type bin \ + -g \ + --out-dir "$DIR"/target/debug \ + --emit=dep-info,link \ + -L dependency="$DIR"/target/debug/deps \ + --extern serde_json=$(echo "$DIR"/target/debug/deps/libserde_json-*.rlib) \ + --extern serde=$(echo "$DIR"/target/debug/deps/libserde-*.rlib) \ + --extern serde_derive="$DIR"/target/debug/deps/libserde_derive.so diff --git a/tmp_test/src/main.rs b/tmp_test/src/main.rs new file mode 100644 index 00000000..bc3e30d4 --- /dev/null +++ b/tmp_test/src/main.rs @@ -0,0 +1,16 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; +extern crate serde_json; + +#[derive(Serialize)] +enum Macros { + #[serde(rename = "macros 1.1")] + OnePointOne, +} + +fn main() { + let s = Macros::OnePointOne; + println!("{}", serde_json::to_string(&s).unwrap()); +} From d36f28971c3a345bf01af34942f9139a9a208c36 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Aug 2016 23:55:11 -0700 Subject: [PATCH 008/111] Support no_std in forward_to_deserialize macro --- serde/src/macros.rs | 257 ++++++++++++++++++++++++++------------------ 1 file changed, 152 insertions(+), 105 deletions(-) diff --git a/serde/src/macros.rs b/serde/src/macros.rs index a997a148..6064c87e 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -1,3 +1,154 @@ +#[cfg(feature = "std")] +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_method { + ($func:ident($($arg:ty),*)) => { + #[inline] + fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error> + where __V: $crate::de::Visitor + { + self.deserialize(visitor) + } + }; +} + +#[cfg(not(feature = "std"))] +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_method { + ($func:ident($($arg:ty),*)) => { + #[inline] + fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error> + where __V: $crate::de::Visitor + { + self.deserialize(visitor) + } + }; +} + +#[cfg(feature = "std")] +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_enum { + () => { + #[inline] + fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error> + where __V: $crate::de::EnumVisitor + { + Err($crate::de::Error::invalid_type($crate::de::Type::Enum)) + } + }; +} + +#[cfg(not(feature = "std"))] +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_enum { + () => { + #[inline] + fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::core::result::Result<__V::Value, Self::Error> + where __V: $crate::de::EnumVisitor + { + Err($crate::de::Error::invalid_type($crate::de::Type::Enum)) + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! forward_to_deserialize_helper { + (bool) => { + forward_to_deserialize_method!{deserialize_bool()} + }; + (usize) => { + forward_to_deserialize_method!{deserialize_usize()} + }; + (u8) => { + forward_to_deserialize_method!{deserialize_u8()} + }; + (u16) => { + forward_to_deserialize_method!{deserialize_u16()} + }; + (u32) => { + forward_to_deserialize_method!{deserialize_u32()} + }; + (u64) => { + forward_to_deserialize_method!{deserialize_u64()} + }; + (isize) => { + forward_to_deserialize_method!{deserialize_isize()} + }; + (i8) => { + forward_to_deserialize_method!{deserialize_i8()} + }; + (i16) => { + forward_to_deserialize_method!{deserialize_i16()} + }; + (i32) => { + forward_to_deserialize_method!{deserialize_i32()} + }; + (i64) => { + forward_to_deserialize_method!{deserialize_i64()} + }; + (f32) => { + forward_to_deserialize_method!{deserialize_f32()} + }; + (f64) => { + forward_to_deserialize_method!{deserialize_f64()} + }; + (char) => { + forward_to_deserialize_method!{deserialize_char()} + }; + (str) => { + forward_to_deserialize_method!{deserialize_str()} + }; + (string) => { + forward_to_deserialize_method!{deserialize_string()} + }; + (unit) => { + forward_to_deserialize_method!{deserialize_unit()} + }; + (option) => { + forward_to_deserialize_method!{deserialize_option()} + }; + (seq) => { + forward_to_deserialize_method!{deserialize_seq()} + }; + (seq_fixed_size) => { + forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)} + }; + (bytes) => { + forward_to_deserialize_method!{deserialize_bytes()} + }; + (map) => { + forward_to_deserialize_method!{deserialize_map()} + }; + (unit_struct) => { + forward_to_deserialize_method!{deserialize_unit_struct(&'static str)} + }; + (newtype_struct) => { + forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)} + }; + (tuple_struct) => { + forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)} + }; + (struct) => { + forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])} + }; + (struct_field) => { + forward_to_deserialize_method!{deserialize_struct_field()} + }; + (tuple) => { + forward_to_deserialize_method!{deserialize_tuple(usize)} + }; + (ignored_any) => { + forward_to_deserialize_method!{deserialize_ignored_any()} + }; + (enum) => { + forward_to_deserialize_enum!(); + }; +} + /// Helper to forward `Deserializer` methods to `Deserializer::deserialize`. /// Every given method ignores all arguments and forwards to `deserialize`. /// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a @@ -22,111 +173,7 @@ /// [1]: https://github.com/serde-rs/serde/issues/521 #[macro_export] macro_rules! forward_to_deserialize { - (@func bool) => { - forward_to_deserialize!{@forward deserialize_bool()} - }; - (@func usize) => { - forward_to_deserialize!{@forward deserialize_usize()} - }; - (@func u8) => { - forward_to_deserialize!{@forward deserialize_u8()} - }; - (@func u16) => { - forward_to_deserialize!{@forward deserialize_u16()} - }; - (@func u32) => { - forward_to_deserialize!{@forward deserialize_u32()} - }; - (@func u64) => { - forward_to_deserialize!{@forward deserialize_u64()} - }; - (@func isize) => { - forward_to_deserialize!{@forward deserialize_isize()} - }; - (@func i8) => { - forward_to_deserialize!{@forward deserialize_i8()} - }; - (@func i16) => { - forward_to_deserialize!{@forward deserialize_i16()} - }; - (@func i32) => { - forward_to_deserialize!{@forward deserialize_i32()} - }; - (@func i64) => { - forward_to_deserialize!{@forward deserialize_i64()} - }; - (@func f32) => { - forward_to_deserialize!{@forward deserialize_f32()} - }; - (@func f64) => { - forward_to_deserialize!{@forward deserialize_f64()} - }; - (@func char) => { - forward_to_deserialize!{@forward deserialize_char()} - }; - (@func str) => { - forward_to_deserialize!{@forward deserialize_str()} - }; - (@func string) => { - forward_to_deserialize!{@forward deserialize_string()} - }; - (@func unit) => { - forward_to_deserialize!{@forward deserialize_unit()} - }; - (@func option) => { - forward_to_deserialize!{@forward deserialize_option()} - }; - (@func seq) => { - forward_to_deserialize!{@forward deserialize_seq()} - }; - (@func seq_fixed_size) => { - forward_to_deserialize!{@forward deserialize_seq_fixed_size(usize)} - }; - (@func bytes) => { - forward_to_deserialize!{@forward deserialize_bytes()} - }; - (@func map) => { - forward_to_deserialize!{@forward deserialize_map()} - }; - (@func unit_struct) => { - forward_to_deserialize!{@forward deserialize_unit_struct(&'static str)} - }; - (@func newtype_struct) => { - forward_to_deserialize!{@forward deserialize_newtype_struct(&'static str)} - }; - (@func tuple_struct) => { - forward_to_deserialize!{@forward deserialize_tuple_struct(&'static str, usize)} - }; - (@func struct) => { - forward_to_deserialize!{@forward deserialize_struct(&'static str, &'static [&'static str])} - }; - (@func struct_field) => { - forward_to_deserialize!{@forward deserialize_struct_field()} - }; - (@func tuple) => { - forward_to_deserialize!{@forward deserialize_tuple(usize)} - }; - (@func enum) => { - #[inline] - fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error> - where __V: $crate::de::EnumVisitor - { - Err($crate::de::Error::invalid_type($crate::de::Type::Enum)) - } - }; - (@func ignored_any) => { - forward_to_deserialize!{@forward deserialize_ignored_any()} - }; - (@forward $func:ident($($arg:ty),*)) => { - #[inline] - fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor - { - self.deserialize(visitor) - } - }; - ($($func:ident)*) => { - $(forward_to_deserialize!{@func $func})* + $(forward_to_deserialize_helper!{$func})* }; } From 3c45e5c7a5415bcfee9b21ea81c78b60a5165094 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 30 Aug 2016 23:55:08 -0700 Subject: [PATCH 009/111] Next iteration --- serde_derive/src/lib.rs | 2 +- tmp_test/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index d0cc0ef9..f4d592d6 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(rustc_macro, rustc_macro_lib)] extern crate rustc_macro; extern crate serde_codegen; diff --git a/tmp_test/src/main.rs b/tmp_test/src/main.rs index bc3e30d4..8e4c43b6 100644 --- a/tmp_test/src/main.rs +++ b/tmp_test/src/main.rs @@ -4,7 +4,7 @@ extern crate serde_derive; extern crate serde_json; -#[derive(Serialize)] +#[derive(Serialize, Deserialize)] enum Macros { #[serde(rename = "macros 1.1")] OnePointOne, From 4bb92790748cd89449a1969b807ac31373e84bb8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 31 Aug 2016 12:53:27 -0700 Subject: [PATCH 010/111] Bump syntex to 0.43 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 18 ++++----- serde_codegen_internals/Cargo.toml | 6 +-- serde_codegen_internals/src/attr.rs | 58 +++++++++++++++++++---------- serde_macros/Cargo.toml | 8 ++-- serde_test/Cargo.toml | 4 +- testing/Cargo.toml | 2 +- 7 files changed, 59 insertions(+), 39 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 59ffaf2a..95064905 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.4" +version = "0.8.5" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 36f705a5..9bf5a783 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.4" +version = "0.8.5" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -25,14 +25,14 @@ with-syntex = [ ] [build-dependencies] -quasi_codegen = { version = "^0.18.0", optional = true } -syntex = { version = "^0.42.2", optional = true } +quasi_codegen = { version = "^0.19.0", optional = true } +syntex = { version = "^0.43.0", optional = true } [dependencies] -aster = { version = "^0.25.0", default-features = false } +aster = { version = "^0.26.0", default-features = false } clippy = { version = "^0.*", optional = true } -quasi = { version = "^0.18.0", default-features = false } -quasi_macros = { version = "^0.18.0", optional = true } -serde_codegen_internals = { version = "=0.7.0", default-features = false, path = "../serde_codegen_internals" } -syntex = { version = "^0.42.2", optional = true } -syntex_syntax = { version = "^0.42.0", optional = true } +quasi = { version = "^0.19.0", default-features = false } +quasi_macros = { version = "^0.19.0", optional = true } +serde_codegen_internals = { version = "=0.8.0", default-features = false, path = "../serde_codegen_internals" } +syntex = { version = "^0.43.0", optional = true } +syntex_syntax = { version = "^0.43.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 95750d3e..3219579d 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.7.0" +version = "0.8.0" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." @@ -17,5 +17,5 @@ with-syntex = ["syntex_syntax", "syntex_errors"] [dependencies] clippy = { version = "^0.*", optional = true } -syntex_syntax = { version = "^0.42.0", optional = true } -syntex_errors = { version = "^0.42.0", optional = true } +syntex_syntax = { version = "^0.43.0", optional = true } +syntex_errors = { version = "^0.43.0", optional = true } diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 8d8d595b..a4dd2ce3 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -8,8 +8,7 @@ use syntax::fold::Folder; use syntax::parse::parser::{Parser, PathStyle}; use syntax::parse::token::{self, InternedString}; use syntax::parse; -use syntax::print::pprust::{lit_to_string, meta_item_to_string}; -use syntax::ptr::P; +use syntax::print::pprust::{lit_to_string, meta_item_to_string, meta_list_item_to_string}; use syntax::tokenstream::{self, TokenTree}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints @@ -165,7 +164,7 @@ impl Item { cx.span_err( meta_item.span, &format!("unknown serde container attribute `{}`", - meta_item_to_string(meta_item))); + meta_item_to_string(&meta_item))); } } } @@ -236,7 +235,7 @@ impl Variant { cx.span_err( meta_item.span, &format!("unknown serde variant attribute `{}`", - meta_item_to_string(meta_item))); + meta_item_to_string(&meta_item))); } } } @@ -384,7 +383,7 @@ impl Field { cx.span_err( meta_item.span, &format!("unknown serde field attribute `{}`", - meta_item_to_string(meta_item))); + meta_item_to_string(&meta_item))); } } } @@ -454,7 +453,7 @@ type SerAndDe = (Option>, Option>); fn get_ser_and_de( cx: &ExtCtxt, attribute: &'static str, - items: &[P], + items: &[ast::NestedMetaItem], f: F ) -> Result, ()> where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result, @@ -464,15 +463,29 @@ fn get_ser_and_de( for item in items { match item.node { - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => { - if let Ok(v) = f(cx, name, lit) { - ser_item.set(item.span, v); - } - } + ast::NestedMetaItemKind::MetaItem(ref meta_item) => { + match meta_item.node { + ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => { + if let Ok(v) = f(cx, name, lit) { + ser_item.set(item.span, v); + } + } - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => { - if let Ok(v) = f(cx, name, lit) { - de_item.set(item.span, v); + ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => { + if let Ok(v) = f(cx, name, lit) { + de_item.set(item.span, v); + } + } + + _ => { + cx.span_err( + item.span, + &format!("unknown {} attribute `{}`", + attribute, + meta_item_to_string(meta_item))); + + return Err(()); + } } } @@ -481,7 +494,7 @@ fn get_ser_and_de( item.span, &format!("unknown {} attribute `{}`", attribute, - meta_item_to_string(item))); + meta_list_item_to_string(item))); return Err(()); } @@ -493,23 +506,30 @@ fn get_ser_and_de( fn get_renames( cx: &ExtCtxt, - items: &[P], + items: &[ast::NestedMetaItem], ) -> Result, ()> { get_ser_and_de(cx, "rename", items, get_str_from_lit) } fn get_where_predicates( cx: &ExtCtxt, - items: &[P], + items: &[ast::NestedMetaItem], ) -> Result>, ()> { get_ser_and_de(cx, "bound", items, parse_lit_into_where) } -pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option<&[P]> { +pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option> { match attr.node.value.node { ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => { attr::mark_used(attr); - Some(items) + Some(items.iter().filter_map(|item| { + match item.node { + ast::NestedMetaItemKind::MetaItem(ref meta_item) => { + Some((*meta_item.clone()).clone()) + } + _ => None, + } + }).collect()) } _ => None } diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml index f9c832d2..805c8647 100644 --- a/serde_macros/Cargo.toml +++ b/serde_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_macros" -version = "0.8.4" +version = "0.8.5" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,14 +23,14 @@ unstable-testing = [ [dependencies] clippy = { version = "^0.*", optional = true } -serde_codegen = { version = "=0.8.4", default-features = false, features = ["unstable"], path = "../serde_codegen" } +serde_codegen = { version = "=0.8.5", default-features = false, features = ["unstable"], path = "../serde_codegen" } [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" rustc-serialize = "^0.3.16" -serde = { version = "0.8.4", path = "../serde" } -serde_test = { version = "0.8.4", path = "../serde_test" } +serde = { version = "0.8.5", path = "../serde" } +serde_test = { version = "0.8.5", path = "../serde_test" } [[test]] name = "test" diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 878164e5..5ebf58a1 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.4" +version = "0.8.5" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.4", path = "../serde" } +serde = { version = "0.8.5", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 9f9fe69e..b21f8889 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.4" +version = "0.8.5" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 54cee86fd3b8e600b712c6dd3ee733a1c85ea90d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 31 Aug 2016 20:14:44 -0700 Subject: [PATCH 011/111] Bump to 0.8.5 --- serde_derive/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 8702b267..50629ffc 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -15,4 +15,4 @@ name = "serde_derive" rustc-macro = true [dependencies] -serde_codegen = { version = "=0.8.4", path = "../serde_codegen" } +serde_codegen = { version = "=0.8.5", path = "../serde_codegen" } From cdb0e6c899cd857ee069c73ed05be64b154e12a6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 31 Aug 2016 21:05:40 -0700 Subject: [PATCH 012/111] Remove build script in favor of rust-lang/cargo#3064 --- tmp_test/build.sh | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100755 tmp_test/build.sh diff --git a/tmp_test/build.sh b/tmp_test/build.sh deleted file mode 100755 index a2ed781b..00000000 --- a/tmp_test/build.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -set -xeuo pipefail - -DIR=$(cd "$(dirname "$0")" && pwd) - -export RUSTC=${RUSTC:-$HOME/.local/bin/rustc} - -cargo build || true - -"$RUSTC" \ - "$DIR"/../serde_derive/src/lib.rs \ - --crate-name serde_derive \ - --crate-type rustc-macro \ - -C prefer-dynamic \ - -g \ - --out-dir "$DIR"/target/debug/deps \ - --emit=dep-info,link \ - -L dependency="$DIR"/target/debug/deps \ - --extern serde_codegen="$DIR"/target/debug/deps/libserde_codegen.rlib - -"$RUSTC" \ - src/main.rs \ - --crate-name tmp_test \ - --crate-type bin \ - -g \ - --out-dir "$DIR"/target/debug \ - --emit=dep-info,link \ - -L dependency="$DIR"/target/debug/deps \ - --extern serde_json=$(echo "$DIR"/target/debug/deps/libserde_json-*.rlib) \ - --extern serde=$(echo "$DIR"/target/debug/deps/libserde-*.rlib) \ - --extern serde_derive="$DIR"/target/debug/deps/libserde_derive.so From 87a402a7513892f432f5342b5816472b65cd7fce Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 1 Sep 2016 11:17:35 -0700 Subject: [PATCH 013/111] Remove rustc_macro test crate --- tmp_test/Cargo.toml | 9 --------- tmp_test/src/main.rs | 16 ---------------- 2 files changed, 25 deletions(-) delete mode 100644 tmp_test/Cargo.toml delete mode 100644 tmp_test/src/main.rs diff --git a/tmp_test/Cargo.toml b/tmp_test/Cargo.toml deleted file mode 100644 index ba3866cb..00000000 --- a/tmp_test/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "tmp-test" -version = "0.1.0" -authors = ["David Tolnay "] - -[dependencies] -serde = "0.8" -serde_derive = { path = "../serde_derive" } -serde_json = "0.8" diff --git a/tmp_test/src/main.rs b/tmp_test/src/main.rs deleted file mode 100644 index 8e4c43b6..00000000 --- a/tmp_test/src/main.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(rustc_macro)] - -#[macro_use] -extern crate serde_derive; -extern crate serde_json; - -#[derive(Serialize, Deserialize)] -enum Macros { - #[serde(rename = "macros 1.1")] - OnePointOne, -} - -fn main() { - let s = Macros::OnePointOne; - println!("{}", serde_json::to_string(&s).unwrap()); -} From 88d845c4d1ff8453a7c321b4efa1fb95b6aa0d99 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 1 Sep 2016 21:28:40 -0700 Subject: [PATCH 014/111] Include! test suite for serde_derive --- serde_derive/Cargo.toml | 5 +++++ serde_derive/src/lib.rs | 1 + serde_derive/tests/test.rs | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 serde_derive/tests/test.rs diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 50629ffc..6384da20 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -16,3 +16,8 @@ rustc-macro = true [dependencies] serde_codegen = { version = "=0.8.5", path = "../serde_codegen" } + +[dev-dependencies] +fnv = "1.0" +serde = { version = "0.8.5", path = "../serde" } +serde_test = { version = "0.8.5", path = "../serde_test" } diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index f4d592d6..aa7bba60 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,4 +1,5 @@ #![feature(rustc_macro, rustc_macro_lib)] +#![cfg(not(test))] extern crate rustc_macro; extern crate serde_codegen; diff --git a/serde_derive/tests/test.rs b/serde_derive/tests/test.rs new file mode 100644 index 00000000..ff8ac572 --- /dev/null +++ b/serde_derive/tests/test.rs @@ -0,0 +1,8 @@ +#![feature(test, rustc_macro, rustc_attrs)] + +#[macro_use] +extern crate serde_derive; + +extern crate test; + +include!("../../testing/tests/test.rs.in"); From ac1128a64711f309cf02afae2a9156523083ddd7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 1 Sep 2016 21:28:58 -0700 Subject: [PATCH 015/111] Update serde_derive to 0.8.5 --- serde_derive/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 6384da20..314080d1 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.4" +version = "0.8.5" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" From 248d937f9a969a5dec5ffef7ae0e100e3c3fec5f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 1 Sep 2016 22:06:12 -0700 Subject: [PATCH 016/111] Release 0.8.6 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_macros/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 95064905..748d2938 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.5" +version = "0.8.6" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 9bf5a783..0d119459 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.5" +version = "0.8.6" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 314080d1..b2434f98 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.5" +version = "0.8.6" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,9 +15,9 @@ name = "serde_derive" rustc-macro = true [dependencies] -serde_codegen = { version = "=0.8.5", path = "../serde_codegen" } +serde_codegen = { version = "=0.8.6", path = "../serde_codegen" } [dev-dependencies] fnv = "1.0" -serde = { version = "0.8.5", path = "../serde" } -serde_test = { version = "0.8.5", path = "../serde_test" } +serde = { version = "0.8.6", path = "../serde" } +serde_test = { version = "0.8.6", path = "../serde_test" } diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml index 805c8647..21f056f8 100644 --- a/serde_macros/Cargo.toml +++ b/serde_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_macros" -version = "0.8.5" +version = "0.8.6" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,14 +23,14 @@ unstable-testing = [ [dependencies] clippy = { version = "^0.*", optional = true } -serde_codegen = { version = "=0.8.5", default-features = false, features = ["unstable"], path = "../serde_codegen" } +serde_codegen = { version = "=0.8.6", default-features = false, features = ["unstable"], path = "../serde_codegen" } [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" rustc-serialize = "^0.3.16" -serde = { version = "0.8.5", path = "../serde" } -serde_test = { version = "0.8.5", path = "../serde_test" } +serde = { version = "0.8.6", path = "../serde" } +serde_test = { version = "0.8.6", path = "../serde_test" } [[test]] name = "test" diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 5ebf58a1..daaec554 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.5" +version = "0.8.6" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.5", path = "../serde" } +serde = { version = "0.8.6", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index b21f8889..7b507399 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.5" +version = "0.8.6" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 14446af53750958303a2bf6956562f5fd7f9eed7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 2 Sep 2016 11:42:26 -0700 Subject: [PATCH 017/111] Fix "variable does not need to be mutable" warning --- serde_codegen/src/ser.rs | 40 +++++++++++++++++++++++++++++++++------ testing/tests/test_gen.rs | 10 ++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 266dc482..19b95814 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -4,6 +4,7 @@ use syntax::ast::{self, Ident, MetaItem}; use syntax::codemap::Span; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; +use syntax::tokenstream::TokenTree; use bound; use span; @@ -226,9 +227,10 @@ fn serialize_tuple_struct( let type_name = name_expr(builder, item_attrs.name()); let len = serialize_stmts.len(); + let let_mut = mut_if_nonzero(cx, len); quote_block!(cx, { - let mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); + let $let_mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); $serialize_stmts _serializer.serialize_tuple_struct_end(state) }).unwrap() @@ -253,8 +255,12 @@ fn serialize_struct( ); let type_name = name_expr(builder, item_attrs.name()); - let len = fields.iter() + + let serialized_fields: Vec<_> = fields.iter() .filter(|&field| !field.attrs.skip_serializing()) + .collect(); + + let len = serialized_fields.iter() .map(|field| { let ident = field.ident.expect("struct has unnamed fields"); let field_expr = quote_expr!(cx, &self.$ident); @@ -266,8 +272,10 @@ fn serialize_struct( }) .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); + let let_mut = mut_if_nonzero(cx, serialized_fields.len()); + quote_block!(cx, { - let mut state = try!(_serializer.serialize_struct($type_name, $len)); + let $let_mut state = try!(_serializer.serialize_struct($type_name, $len)); $serialize_fields _serializer.serialize_struct_end(state) }).unwrap() @@ -458,9 +466,10 @@ fn serialize_tuple_variant( ); let len = serialize_stmts.len(); + let let_mut = mut_if_nonzero(cx, len); quote_block!(cx, { - let mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); + let $let_mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); $serialize_stmts _serializer.serialize_tuple_variant_end(state) }).unwrap() @@ -488,8 +497,11 @@ fn serialize_struct_variant( ); let item_name = name_expr(builder, item_attrs.name()); - let len = fields.iter() + let serialized_fields: Vec<_> = fields.iter() .filter(|&field| !field.attrs.skip_serializing()) + .collect(); + + let len = serialized_fields.iter() .map(|field| { let ident = field.ident.expect("struct has unnamed fields"); let field_expr = quote_expr!(cx, $ident); @@ -501,8 +513,10 @@ fn serialize_struct_variant( }) .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); + let let_mut = mut_if_nonzero(cx, serialized_fields.len()); + quote_block!(cx, { - let mut state = try!(_serializer.serialize_struct_variant( + let $let_mut state = try!(_serializer.serialize_struct_variant( $item_name, $variant_index, $variant_name, @@ -637,3 +651,17 @@ fn name_expr( ) -> P { builder.expr().str(name.serialize_name()) } + +// Serialization of an empty struct results in code like: +// +// let mut state = try!(serializer.serialize_struct("S", 0)); +// serializer.serialize_struct_end(state) +// +// where we want to omit the `mut` to avoid a warning. +fn mut_if_nonzero(cx: &ExtCtxt, n: usize) -> Vec { + if n == 0 { + Vec::new() + } else { + quote_tokens!(cx, mut) + } +} diff --git a/testing/tests/test_gen.rs b/testing/tests/test_gen.rs index 7d648f57..3e2fe382 100644 --- a/testing/tests/test_gen.rs +++ b/testing/tests/test_gen.rs @@ -187,6 +187,16 @@ fn test_gen() { #[serde(bound(deserialize = "T::Owned: Deserialize"))] struct CowT<'a, T: ?Sized + 'a + ToOwned>(Cow<'a, T>); assert::>(); + + #[derive(Serialize, Deserialize)] + struct EmptyStruct {} + assert::(); + + #[derive(Serialize, Deserialize)] + enum EmptyEnumVariant { + EmptyStruct {}, + } + assert::(); } ////////////////////////////////////////////////////////////////////////// From 869ebd9e4e8bbe646d790f49d95f9ec609fe9001 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 2 Sep 2016 17:22:58 -0700 Subject: [PATCH 018/111] Remove `if !false { ... }` from generated serialization code --- serde_codegen/src/ser.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 266dc482..ed2f5589 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -532,19 +532,21 @@ fn serialize_tuple_struct_visitor( }; let skip = field.attrs.skip_serializing_if() - .map(|path| quote_expr!(cx, $path($field_expr))) - .unwrap_or(quote_expr!(cx, false)); + .map(|path| quote_expr!(cx, $path($field_expr))); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_with(cx, builder, &structure_ty, generics, &field.ty, path, field_expr); } - quote_stmt!(cx, - if !$skip { - try!(_serializer.$func(&mut state, $field_expr)); - } - ).unwrap() + let ser = quote_stmt!(cx, + try!(_serializer.$func(&mut state, $field_expr)); + ).unwrap(); + + match skip { + None => ser, + Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(), + } }) .collect() } @@ -571,19 +573,21 @@ fn serialize_struct_visitor( let key_expr = name_expr(builder, field.attrs.name()); let skip = field.attrs.skip_serializing_if() - .map(|path| quote_expr!(cx, $path($field_expr))) - .unwrap_or(quote_expr!(cx, false)); + .map(|path| quote_expr!(cx, $path($field_expr))); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_with(cx, builder, &structure_ty, generics, &field.ty, path, field_expr) } - quote_stmt!(cx, - if !$skip { - try!(_serializer.$func(&mut state, $key_expr, $field_expr)); - } - ).unwrap() + let ser = quote_stmt!(cx, + try!(_serializer.$func(&mut state, $key_expr, $field_expr)); + ).unwrap(); + + match skip { + None => ser, + Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(), + } }) .collect() } From d1ce4d62c919befbe37e84b2c18959e95aabe73a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 2 Sep 2016 18:07:26 -0700 Subject: [PATCH 019/111] Change to expression so that syntex keeps the semicolon --- serde_codegen/src/ser.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index ed2f5589..d3c91396 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -539,12 +539,12 @@ fn serialize_tuple_struct_visitor( &structure_ty, generics, &field.ty, path, field_expr); } - let ser = quote_stmt!(cx, + let ser = quote_expr!(cx, try!(_serializer.$func(&mut state, $field_expr)); - ).unwrap(); + ); match skip { - None => ser, + None => quote_stmt!(cx, $ser).unwrap(), Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(), } }) @@ -580,12 +580,12 @@ fn serialize_struct_visitor( &structure_ty, generics, &field.ty, path, field_expr) } - let ser = quote_stmt!(cx, + let ser = quote_expr!(cx, try!(_serializer.$func(&mut state, $key_expr, $field_expr)); - ).unwrap(); + ); match skip { - None => ser, + None => quote_stmt!(cx, $ser).unwrap(), Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(), } }) From 35be61d85f0a18aec8ecaa3f398aa76ace1132f7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 5 Sep 2016 08:02:35 -0700 Subject: [PATCH 020/111] Resolve merge conflict --- serde/src/de/value.rs | 58 ++++++------------------------------------- 1 file changed, 8 insertions(+), 50 deletions(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 67ad278d..00b07107 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -734,28 +734,6 @@ impl de::Deserializer for MapDeserializer visitor.visit_map(self) } -<<<<<<< HEAD - forward_to_deserialize! { - bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string - unit option seq seq_fixed_size bytes map unit_struct newtype_struct - tuple_struct struct struct_field tuple enum ignored_any -||||||| merged common ancestors - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_seq, deserialize_seq_fixed_size, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option -======= fn deserialize_seq(&mut self, mut visitor: V_) -> Result where V_: de::Visitor, { @@ -772,21 +750,10 @@ impl de::Deserializer for MapDeserializer } } - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct, - deserialize_option ->>>>>>> origin/master + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option bytes map unit_struct newtype_struct tuple_struct struct + struct_field tuple enum ignored_any } } @@ -879,19 +846,10 @@ impl de::Deserializer for PairDeserializer { type Error = E; - de_forward_to_deserialize!{ - deserialize_bool, - deserialize_f64, deserialize_f32, - deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, - deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, - deserialize_char, deserialize_str, deserialize_string, - deserialize_ignored_any, - deserialize_bytes, - deserialize_unit_struct, deserialize_unit, deserialize_option, - deserialize_map, deserialize_newtype_struct, deserialize_struct_field, - deserialize_tuple, - deserialize_enum, - deserialize_struct, deserialize_tuple_struct + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string + unit option bytes map unit_struct newtype_struct tuple_struct struct + struct_field tuple enum ignored_any } fn deserialize(&mut self, visitor: V) -> Result From 08bc2d2e76e9d9965c3067d5b5f54dfe92ab7192 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 5 Sep 2016 08:09:23 -0700 Subject: [PATCH 021/111] Use constructors to create Bytes and ByteBuf --- serde/src/bytes.rs | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs index 12e42e75..a732712c 100644 --- a/serde/src/bytes.rs +++ b/serde/src/bytes.rs @@ -40,18 +40,14 @@ impl<'a> fmt::Debug for Bytes<'a> { impl<'a> From<&'a [u8]> for Bytes<'a> { fn from(bytes: &'a [u8]) -> Self { - Bytes { - bytes: bytes, - } + Bytes::new(bytes) } } #[cfg(any(feature = "std", feature = "collections"))] impl<'a> From<&'a Vec> for Bytes<'a> { fn from(bytes: &'a Vec) -> Self { - Bytes { - bytes: bytes, - } + Bytes::new(bytes) } } @@ -99,16 +95,12 @@ mod bytebuf { impl ByteBuf { /// Construct a new, empty `ByteBuf`. pub fn new() -> Self { - ByteBuf { - bytes: Vec::new(), - } + ByteBuf::from(Vec::new()) } /// Construct a new, empty `ByteBuf` with the specified capacity. pub fn with_capacity(cap: usize) -> Self { - ByteBuf { - bytes: Vec::with_capacity(cap) - } + ByteBuf::from(Vec::with_capacity(cap)) } /// Wrap existing bytes in a `ByteBuf`. @@ -137,9 +129,7 @@ mod bytebuf { impl From> for ByteBuf { fn from(bytes: Vec) -> Self { - ByteBuf { - bytes: bytes, - } + ByteBuf::from(bytes) } } @@ -195,9 +185,7 @@ mod bytebuf { fn visit_unit(&mut self) -> Result where E: de::Error, { - Ok(ByteBuf { - bytes: Vec::new(), - }) + Ok(ByteBuf::new()) } #[inline] @@ -213,9 +201,7 @@ mod bytebuf { try!(visitor.end()); - Ok(ByteBuf { - bytes: values, - }) + Ok(ByteBuf::from(values)) } #[inline] @@ -229,9 +215,7 @@ mod bytebuf { fn visit_byte_buf(&mut self, v: Vec) -> Result where E: de::Error, { - Ok(ByteBuf { - bytes: v, - }) + Ok(ByteBuf::from(v)) } } From e03dedabe488535cca6feb797e94a0ca455ee5bd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 5 Sep 2016 08:22:17 -0700 Subject: [PATCH 022/111] Use peekable iterator to check for nonzero serialized fields --- serde_codegen/src/ser.rs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 19b95814..1639d067 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -227,7 +227,7 @@ fn serialize_tuple_struct( let type_name = name_expr(builder, item_attrs.name()); let len = serialize_stmts.len(); - let let_mut = mut_if_nonzero(cx, len); + let let_mut = mut_if(cx, len > 0); quote_block!(cx, { let $let_mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); @@ -256,11 +256,13 @@ fn serialize_struct( let type_name = name_expr(builder, item_attrs.name()); - let serialized_fields: Vec<_> = fields.iter() + let mut serialized_fields = fields.iter() .filter(|&field| !field.attrs.skip_serializing()) - .collect(); + .peekable(); - let len = serialized_fields.iter() + let let_mut = mut_if(cx, serialized_fields.peek().is_some()); + + let len = serialized_fields .map(|field| { let ident = field.ident.expect("struct has unnamed fields"); let field_expr = quote_expr!(cx, &self.$ident); @@ -272,8 +274,6 @@ fn serialize_struct( }) .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); - let let_mut = mut_if_nonzero(cx, serialized_fields.len()); - quote_block!(cx, { let $let_mut state = try!(_serializer.serialize_struct($type_name, $len)); $serialize_fields @@ -466,7 +466,7 @@ fn serialize_tuple_variant( ); let len = serialize_stmts.len(); - let let_mut = mut_if_nonzero(cx, len); + let let_mut = mut_if(cx, len > 0); quote_block!(cx, { let $let_mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); @@ -497,11 +497,14 @@ fn serialize_struct_variant( ); let item_name = name_expr(builder, item_attrs.name()); - let serialized_fields: Vec<_> = fields.iter() - .filter(|&field| !field.attrs.skip_serializing()) - .collect(); - let len = serialized_fields.iter() + let mut serialized_fields = fields.iter() + .filter(|&field| !field.attrs.skip_serializing()) + .peekable(); + + let let_mut = mut_if(cx, serialized_fields.peek().is_some()); + + let len = serialized_fields .map(|field| { let ident = field.ident.expect("struct has unnamed fields"); let field_expr = quote_expr!(cx, $ident); @@ -513,8 +516,6 @@ fn serialize_struct_variant( }) .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); - let let_mut = mut_if_nonzero(cx, serialized_fields.len()); - quote_block!(cx, { let $let_mut state = try!(_serializer.serialize_struct_variant( $item_name, @@ -658,10 +659,10 @@ fn name_expr( // serializer.serialize_struct_end(state) // // where we want to omit the `mut` to avoid a warning. -fn mut_if_nonzero(cx: &ExtCtxt, n: usize) -> Vec { - if n == 0 { - Vec::new() - } else { +fn mut_if(cx: &ExtCtxt, is_mut: bool) -> Vec { + if is_mut { quote_tokens!(cx, mut) + } else { + Vec::new() } } From e85ca8411ec4253cf4705c8b5efd409e5252af32 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 5 Sep 2016 09:39:27 -0700 Subject: [PATCH 023/111] Release 0.8.7 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_macros/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 748d2938..80cd8079 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.6" +version = "0.8.7" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 0d119459..0c515116 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.6" +version = "0.8.7" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index b2434f98..1773569e 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.6" +version = "0.8.7" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,9 +15,9 @@ name = "serde_derive" rustc-macro = true [dependencies] -serde_codegen = { version = "=0.8.6", path = "../serde_codegen" } +serde_codegen = { version = "=0.8.7", path = "../serde_codegen" } [dev-dependencies] fnv = "1.0" -serde = { version = "0.8.6", path = "../serde" } -serde_test = { version = "0.8.6", path = "../serde_test" } +serde = { version = "0.8.7", path = "../serde" } +serde_test = { version = "0.8.7", path = "../serde_test" } diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml index 21f056f8..cec56baf 100644 --- a/serde_macros/Cargo.toml +++ b/serde_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_macros" -version = "0.8.6" +version = "0.8.7" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,14 +23,14 @@ unstable-testing = [ [dependencies] clippy = { version = "^0.*", optional = true } -serde_codegen = { version = "=0.8.6", default-features = false, features = ["unstable"], path = "../serde_codegen" } +serde_codegen = { version = "=0.8.7", default-features = false, features = ["unstable"], path = "../serde_codegen" } [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" rustc-serialize = "^0.3.16" -serde = { version = "0.8.6", path = "../serde" } -serde_test = { version = "0.8.6", path = "../serde_test" } +serde = { version = "0.8.7", path = "../serde" } +serde_test = { version = "0.8.7", path = "../serde_test" } [[test]] name = "test" diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index daaec554..efbd9819 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.6" +version = "0.8.7" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.6", path = "../serde" } +serde = { version = "0.8.7", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 7b507399..f758ddc8 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.6" +version = "0.8.7" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 2212bfbf2ca2850a120f6eb5242d34aad261fc01 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 7 Sep 2016 16:25:22 -0700 Subject: [PATCH 024/111] Result needs to be fully qualified Without this: ``` error[E0244]: wrong number of type arguments --> src/api/accounts.rs:19:10 | 19 | #[derive(Serialize, Deserialize, Debug)] | ^^^^^^^^^^ expected 1 type arguments, found 2 ``` --- serde_codegen/src/ser.rs | 2 +- testing/tests/test_gen.rs | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 8fdc3576..d4883e8e 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -636,7 +636,7 @@ fn wrap_serialize_with( } impl $wrapper_generics _serde::ser::Serialize for $wrapper_ty $where_clause { - fn serialize<__S>(&self, __s: &mut __S) -> Result<(), __S::Error> + fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error> where __S: _serde::ser::Serializer { $path(self.value, __s) diff --git a/testing/tests/test_gen.rs b/testing/tests/test_gen.rs index 3e2fe382..c52ebcad 100644 --- a/testing/tests/test_gen.rs +++ b/testing/tests/test_gen.rs @@ -9,6 +9,11 @@ use self::serde::de::{Deserialize, Deserializer}; use std::borrow::Cow; use std::marker::PhantomData; +// Try to trip up the generated code if it fails to use fully qualified paths. +#[allow(dead_code)] +struct Result; +use std::result::Result as StdResult; + ////////////////////////////////////////////////////////////////////////// #[test] @@ -205,32 +210,32 @@ fn assert() {} fn assert_ser() {} trait SerializeWith { - fn serialize_with(_: &Self, _: &mut S) -> Result<(), S::Error>; + fn serialize_with(_: &Self, _: &mut S) -> StdResult<(), S::Error>; } trait DeserializeWith: Sized { - fn deserialize_with(_: &mut D) -> Result; + fn deserialize_with(_: &mut D) -> StdResult; } // Implements neither Serialize nor Deserialize struct X; -fn ser_x(_: &X, _: &mut S) -> Result<(), S::Error> { +fn ser_x(_: &X, _: &mut S) -> StdResult<(), S::Error> { unimplemented!() } -fn de_x(_: &mut D) -> Result { +fn de_x(_: &mut D) -> StdResult { unimplemented!() } impl SerializeWith for X { - fn serialize_with(_: &Self, _: &mut S) -> Result<(), S::Error> { + fn serialize_with(_: &Self, _: &mut S) -> StdResult<(), S::Error> { unimplemented!() } } impl DeserializeWith for X { - fn deserialize_with(_: &mut D) -> Result { + fn deserialize_with(_: &mut D) -> StdResult { unimplemented!() } } From 7cc36a9cd390ac673f858ba1da0c4165d59a4fbc Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 8 Sep 2016 08:34:20 -0700 Subject: [PATCH 025/111] Release 0.8.8 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_macros/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 80cd8079..93c11cbe 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.7" +version = "0.8.8" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 0c515116..703575e7 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.7" +version = "0.8.8" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 1773569e..66930b14 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.7" +version = "0.8.8" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,9 +15,9 @@ name = "serde_derive" rustc-macro = true [dependencies] -serde_codegen = { version = "=0.8.7", path = "../serde_codegen" } +serde_codegen = { version = "=0.8.8", path = "../serde_codegen" } [dev-dependencies] fnv = "1.0" -serde = { version = "0.8.7", path = "../serde" } -serde_test = { version = "0.8.7", path = "../serde_test" } +serde = { version = "0.8.8", path = "../serde" } +serde_test = { version = "0.8.8", path = "../serde_test" } diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml index cec56baf..ba892a66 100644 --- a/serde_macros/Cargo.toml +++ b/serde_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_macros" -version = "0.8.7" +version = "0.8.8" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,14 +23,14 @@ unstable-testing = [ [dependencies] clippy = { version = "^0.*", optional = true } -serde_codegen = { version = "=0.8.7", default-features = false, features = ["unstable"], path = "../serde_codegen" } +serde_codegen = { version = "=0.8.8", default-features = false, features = ["unstable"], path = "../serde_codegen" } [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" rustc-serialize = "^0.3.16" -serde = { version = "0.8.7", path = "../serde" } -serde_test = { version = "0.8.7", path = "../serde_test" } +serde = { version = "0.8.8", path = "../serde" } +serde_test = { version = "0.8.8", path = "../serde_test" } [[test]] name = "test" diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index efbd9819..c9d6e9b5 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.7" +version = "0.8.8" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.7", path = "../serde" } +serde = { version = "0.8.8", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index f758ddc8..bac9bfa9 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.7" +version = "0.8.8" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From c34baa1e5f219316212ec4dfdcb5b4d6f18473ea Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 10 Sep 2016 21:53:14 -0700 Subject: [PATCH 026/111] No more syntex for serde_derive --- serde_codegen/Cargo.toml | 20 +- serde_codegen/build.rs | 28 -- serde_codegen/src/bound.rs | 56 ++- serde_codegen/src/lib.rs | 183 ++++++++- serde_codegen/src/lib.rs.in | 4 - serde_codegen/src/ser.rs | 531 +++++++++++---------------- serde_codegen/src/span.rs | 43 --- serde_codegen_internals/Cargo.toml | 5 +- serde_codegen_internals/src/ast.rs | 84 ++--- serde_codegen_internals/src/attr.rs | 440 +++++++--------------- serde_codegen_internals/src/ctxt.rs | 29 ++ serde_codegen_internals/src/error.rs | 19 - serde_codegen_internals/src/lib.rs | 17 +- serde_derive/Cargo.toml | 7 +- serde_derive/src/lib.rs | 4 +- 15 files changed, 611 insertions(+), 859 deletions(-) delete mode 100644 serde_codegen/build.rs delete mode 100644 serde_codegen/src/lib.rs.in delete mode 100644 serde_codegen/src/span.rs create mode 100644 serde_codegen_internals/src/ctxt.rs delete mode 100644 serde_codegen_internals/src/error.rs diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 703575e7..9fa605c4 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -8,31 +8,23 @@ homepage = "https://serde.rs" repository = "https://github.com/serde-rs/serde" documentation = "https://serde.rs/codegen.html" keywords = ["serde", "serialization"] -build = "build.rs" -include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"] +include = ["Cargo.toml", "src/**/*.rs"] [features] default = ["with-syntex"] -unstable = ["quasi_macros"] +unstable = [] unstable-testing = ["clippy"] with-syntex = [ - "quasi/with-syntex", - "quasi_codegen", - "quasi_codegen/with-syntex", - "serde_codegen_internals/with-syntex", "syntex", "syntex_syntax", ] - -[build-dependencies] -quasi_codegen = { version = "^0.19.0", optional = true } -syntex = { version = "^0.43.0", optional = true } +with-libsyntax = [] +with-syn = [] [dependencies] -aster = { version = "^0.26.0", default-features = false } clippy = { version = "^0.*", optional = true } -quasi = { version = "^0.19.0", default-features = false } -quasi_macros = { version = "^0.19.0", optional = true } +quote = "0.1" serde_codegen_internals = { version = "=0.8.0", default-features = false, path = "../serde_codegen_internals" } +syn = { version = "0.5", features = ["aster", "visit"] } syntex = { version = "^0.43.0", optional = true } syntex_syntax = { version = "^0.43.0", optional = true } diff --git a/serde_codegen/build.rs b/serde_codegen/build.rs deleted file mode 100644 index 9ff828f2..00000000 --- a/serde_codegen/build.rs +++ /dev/null @@ -1,28 +0,0 @@ -#[cfg(feature = "with-syntex")] -mod inner { - extern crate quasi_codegen; - - use std::env; - use std::path::Path; - use std::thread::spawn; - - pub fn main() { - // put everything into a thread, so users can use `RUST_MIN_STACK` to increase the amount of stack - spawn(|| { - let out_dir = env::var_os("OUT_DIR").unwrap(); - - let src = Path::new("src/lib.rs.in"); - let dst = Path::new(&out_dir).join("lib.rs"); - quasi_codegen::expand(&src, &dst).unwrap(); - }).join().unwrap() - } -} - -#[cfg(not(feature = "with-syntex"))] -mod inner { - pub fn main() {} -} - -fn main() { - inner::main(); -} diff --git a/serde_codegen/src/bound.rs b/serde_codegen/src/bound.rs index 7bd5ddc6..fef77ba3 100644 --- a/serde_codegen/src/bound.rs +++ b/serde_codegen/src/bound.rs @@ -1,9 +1,6 @@ use std::collections::HashSet; -use aster::AstBuilder; - -use syntax::ast; -use syntax::visit; +use syn::{self, aster, visit}; use internals::ast::Item; use internals::attr; @@ -11,10 +8,10 @@ use internals::attr; // Remove the default from every type parameter because in the generated impls // they look like associated types: "error: associated type bindings are not // allowed here". -pub fn without_defaults(generics: &ast::Generics) -> ast::Generics { - ast::Generics { +pub fn without_defaults(generics: &syn::Generics) -> syn::Generics { + syn::Generics { ty_params: generics.ty_params.iter().map(|ty_param| { - ast::TyParam { + syn::TyParam { default: None, .. ty_param.clone() }}).collect(), @@ -23,24 +20,22 @@ pub fn without_defaults(generics: &ast::Generics) -> ast::Generics { } pub fn with_where_predicates( - builder: &AstBuilder, - generics: &ast::Generics, - predicates: &[ast::WherePredicate], -) -> ast::Generics { - builder.from_generics(generics.clone()) + generics: &syn::Generics, + predicates: &[syn::WherePredicate], +) -> syn::Generics { + aster::from_generics(generics.clone()) .with_predicates(predicates.to_vec()) .build() } pub fn with_where_predicates_from_fields( - builder: &AstBuilder, item: &Item, - generics: &ast::Generics, + generics: &syn::Generics, from_field: F, -) -> ast::Generics - where F: Fn(&attr::Field) -> Option<&[ast::WherePredicate]>, +) -> syn::Generics + where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>, { - builder.from_generics(generics.clone()) + aster::from_generics(generics.clone()) .with_predicates( item.body.all_fields() .flat_map(|field| from_field(&field.attrs)) @@ -60,34 +55,33 @@ pub fn with_where_predicates_from_fields( // c: C, // } pub fn with_bound( - builder: &AstBuilder, item: &Item, - generics: &ast::Generics, + generics: &syn::Generics, filter: F, - bound: &ast::Path, -) -> ast::Generics + bound: &syn::Path, +) -> syn::Generics where F: Fn(&attr::Field) -> bool, { struct FindTyParams { // Set of all generic type parameters on the current struct (A, B, C in // the example). Initialized up front. - all_ty_params: HashSet, + all_ty_params: HashSet, // Set of generic type parameters used in fields for which filter // returns true (A and B in the example). Filled in as the visitor sees // them. - relevant_ty_params: HashSet, + relevant_ty_params: HashSet, } impl visit::Visitor for FindTyParams { - fn visit_path(&mut self, path: &ast::Path, _id: ast::NodeId) { + fn visit_path(&mut self, path: &syn::Path) { if let Some(seg) = path.segments.last() { - if seg.identifier.name.as_str() == "PhantomData" { + if seg.ident == "PhantomData" { // Hardcoded exception, because PhantomData implements // Serialize and Deserialize whether or not T implements it. return; } } if !path.global && path.segments.len() == 1 { - let id = path.segments[0].identifier.name; + let id = path.segments[0].ident.clone(); if self.all_ty_params.contains(&id) { self.relevant_ty_params.insert(id); } @@ -97,7 +91,7 @@ pub fn with_bound( } let all_ty_params: HashSet<_> = generics.ty_params.iter() - .map(|ty_param| ty_param.ident.name) + .map(|ty_param| ty_param.ident.clone()) .collect(); let relevant_tys = item.body.all_fields() @@ -112,14 +106,14 @@ pub fn with_bound( visit::walk_ty(&mut visitor, ty); } - builder.from_generics(generics.clone()) + aster::from_generics(generics.clone()) .with_predicates( generics.ty_params.iter() - .map(|ty_param| ty_param.ident.name) + .map(|ty_param| ty_param.ident.clone()) .filter(|id| visitor.relevant_ty_params.contains(id)) - .map(|id| builder.where_predicate() + .map(|id| aster::where_predicate() // the type parameter that is being bounded e.g. T - .bound().build(builder.ty().id(id)) + .bound().build(aster::ty().id(id)) // the bound e.g. Serialize .bound().trait_(bound.clone()).build() .build())) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 55318af6..7de4db6d 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -2,11 +2,8 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", allow(too_many_arguments))] #![cfg_attr(feature = "clippy", allow(used_underscore_binding))] -#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))] -#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))] +#![cfg_attr(feature = "with-libsyntax", feature(rustc_private, plugin))] -extern crate aster; -extern crate quasi; extern crate serde_codegen_internals as internals; #[cfg(feature = "with-syntex")] @@ -16,24 +13,25 @@ extern crate syntex; #[macro_use] extern crate syntex_syntax as syntax; -#[cfg(not(feature = "with-syntex"))] +#[cfg(feature = "with-libsyntax")] #[macro_use] extern crate syntax; -#[cfg(not(feature = "with-syntex"))] +#[cfg(feature = "with-libsyntax")] extern crate rustc_plugin; +extern crate syn; +#[macro_use] +extern crate quote; + #[cfg(feature = "with-syntex")] use std::path::Path; -#[cfg(not(feature = "with-syntex"))] +#[cfg(feature = "with-libsyntax")] use syntax::feature_gate::AttributeType; -#[cfg(feature = "with-syntex")] -include!(concat!(env!("OUT_DIR"), "/lib.rs")); - -#[cfg(not(feature = "with-syntex"))] -include!("lib.rs.in"); +mod bound; +mod ser; #[cfg(feature = "with-syntex")] fn syntex_registry() -> syntex::Registry { @@ -68,7 +66,7 @@ fn syntex_registry() -> syntex::Registry { reg.add_attr("feature(custom_derive)"); reg.add_attr("feature(custom_attribute)"); - reg.add_decorator("derive_Serialize", ser::expand_derive_serialize); + reg.add_decorator("derive_Serialize", expand_derive_serialize); reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize); reg.add_post_expansion_pass(strip_attributes); @@ -102,17 +100,168 @@ pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> syntex::with_extra_stack(expand_thread) } -#[cfg(not(feature = "with-syntex"))] +#[cfg(feature = "with-libsyntax")] pub fn register(reg: &mut rustc_plugin::Registry) { reg.register_syntax_extension( syntax::parse::token::intern("derive_Serialize"), syntax::ext::base::MultiDecorator( - Box::new(ser::expand_derive_serialize))); + Box::new(expand_derive_serialize))); - reg.register_syntax_extension( + /*reg.register_syntax_extension( syntax::parse::token::intern("derive_Deserialize"), syntax::ext::base::MultiDecorator( - Box::new(de::expand_derive_deserialize))); + Box::new(de::expand_derive_deserialize)));*/ reg.register_attribute("serde".to_owned(), AttributeType::Normal); } + +#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] +use syntax::ast::MetaItem; +#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] +use syntax::codemap::Span; +#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] +use syntax::ext::base::{Annotatable, ExtCtxt}; + +#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] +fn expand_derive_serialize( + cx: &mut ExtCtxt, + _span: Span, + meta_item: &MetaItem, + annotatable: &Annotatable, + push: &mut FnMut(Annotatable) +) { + let item = match *annotatable { + Annotatable::Item(ref item) => item, + _ => { + cx.span_err( + meta_item.span, + "`#[derive(Serialize)]` may only be applied to structs and enums"); + return; + } + }; + + use syntax::print::pprust; + let s = pprust::item_to_string(item); + + let syn_item = syn::parse_item(&s).unwrap(); + let expanded = ser::expand_derive_serialize(&syn_item).to_string(); + + use syntax::parse; + let name = "Serialize".to_string(); + let cfg = Vec::new(); + let sess = parse::ParseSess::new(); + let impl_item = parse::parse_item_from_source_str(name, expanded, cfg, &sess); + push(Annotatable::Item(impl_item.unwrap().unwrap())); +} + +#[cfg(feature = "with-syn")] +pub fn expand_single_item(item: &str) -> String { + let syn_item = syn::parse_item(item).unwrap(); + let (ser, de, syn_item) = strip_serde_derives(syn_item); + let expanded_ser = if ser { + Some(ser::expand_derive_serialize(&syn_item)) + } else { + None + }; + let expanded_de = if de { + unimplemented!() + } else { + None:: + }; + let syn_item = strip_serde_attrs(syn_item); + return quote!(#expanded_ser #expanded_de #syn_item).to_string(); + + fn strip_serde_derives(item: syn::Item) -> (bool, bool, syn::Item) { + let mut ser = false; + let mut de = false; + let item = syn::Item { + attrs: item.attrs.into_iter().flat_map(|attr| { + if attr.is_sugared_doc { + return Some(attr); + } + let (name, nested) = match attr.value { + syn::MetaItem::List(name, nested) => (name, nested), + _ => return Some(attr) + }; + if name != "derive" { + return Some(syn::Attribute { + value: syn::MetaItem::List(name, nested), + is_sugared_doc: false, + }); + } + let rest: Vec<_> = nested.into_iter().filter(|nested| { + match *nested { + syn::MetaItem::Word(ref word) if word == "Serialize" => { + ser = true; + false + } + syn::MetaItem::Word(ref word) if word == "Deserialize" => { + de = true; + false + } + _ => true, + } + }).collect(); + if rest.is_empty() { + None + } else { + Some(syn::Attribute { + value: syn::MetaItem::List(name, rest), + is_sugared_doc: false, + }) + } + }).collect(), + ..item + }; + (ser, de, item) + } + + fn strip_serde_attrs(item: syn::Item) -> syn::Item { + syn::Item { + attrs: strip_serde_from_attrs(item.attrs), + body: match item.body { + syn::Body::Enum(variants) => syn::Body::Enum( + variants.into_iter().map(|variant| { + syn::Variant { + ident: variant.ident, + attrs: strip_serde_from_attrs(variant.attrs), + data: strip_serde_from_variant_data(variant.data), + } + }).collect() + ), + syn::Body::Struct(variant_data) => syn::Body::Struct( + strip_serde_from_variant_data(variant_data) + ), + }, + ..item + } + } + + fn strip_serde_from_variant_data(data: syn::VariantData) -> syn::VariantData { + match data { + syn::VariantData::Struct(fields) => syn::VariantData::Struct( + fields.into_iter().map(strip_serde_from_field).collect() + ), + syn::VariantData::Tuple(fields) => syn::VariantData::Tuple( + fields.into_iter().map(strip_serde_from_field).collect() + ), + syn::VariantData::Unit => syn::VariantData::Unit, + } + } + + fn strip_serde_from_field(field: syn::Field) -> syn::Field { + syn::Field { + attrs: strip_serde_from_attrs(field.attrs), + ..field + } + } + + fn strip_serde_from_attrs(attrs: Vec) -> Vec { + attrs.into_iter().filter(|attr| { + match attr.value { + syn::MetaItem::List(ref ident, _) => ident != "serde", + _ => true, + } + }).collect() + } +} diff --git a/serde_codegen/src/lib.rs.in b/serde_codegen/src/lib.rs.in deleted file mode 100644 index 08dd5d3c..00000000 --- a/serde_codegen/src/lib.rs.in +++ /dev/null @@ -1,4 +0,0 @@ -mod bound; -mod de; -mod ser; -mod span; diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index d4883e8e..448c974c 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -1,103 +1,60 @@ -use aster; - -use syntax::ast::{self, Ident, MetaItem}; -use syntax::codemap::Span; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ptr::P; -use syntax::tokenstream::TokenTree; +use syn::{self, aster}; +use quote::Tokens; use bound; -use span; use internals::ast::{Body, Field, Item, Style, Variant}; -use internals::{attr, Error}; +use internals::{self, attr}; -pub fn expand_derive_serialize( - cx: &mut ExtCtxt, - span: Span, - meta_item: &MetaItem, - annotatable: &Annotatable, - push: &mut FnMut(Annotatable) -) { - let item = match *annotatable { - Annotatable::Item(ref item) => item, - _ => { - cx.span_err( - meta_item.span, - "`#[derive(Serialize)]` may only be applied to structs and enums"); - return; - } - }; +pub fn expand_derive_serialize(item: &syn::Item) -> Tokens { + let item = Item::from_ast(&internals::Ctxt::new(), item); - let item = match Item::from_ast(cx, item) { - Ok(item) => item, - Err(Error::UnexpectedItemKind) => { - cx.span_err(item.span, - "`#[derive(Serialize)]` may only be applied to structs and enums"); - return; - } - }; + let impl_generics = build_impl_generics(&item); - let builder = aster::AstBuilder::new().span(span); - - let impl_item = serialize_item(cx, &builder, &item); - push(span::record_expansion(cx, impl_item, "Serialize")) -} - -fn serialize_item( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, -) -> P { - let impl_generics = build_impl_generics(builder, &item); - - let ty = builder.ty().path() - .segment(item.ident).with_generics(impl_generics.clone()).build() + let ty = aster::ty().path() + .segment(item.ident.clone()).with_generics(impl_generics.clone()).build() .build(); - let body = serialize_body(cx, - builder, - &item, + let body = serialize_body(&item, &impl_generics, ty.clone()); let where_clause = &impl_generics.where_clause; - let dummy_const = builder.id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident)); + let dummy_const = aster::id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident)); - quote_item!(cx, + quote! { #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const $dummy_const: () = { + const #dummy_const: () = { extern crate serde as _serde; #[automatically_derived] - 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> where __S: _serde::ser::Serializer - $body + { + #body + } } }; - ).unwrap() + } } // All the generics in the input, plus a bound `T: Serialize` for each generic // field type that will be serialized by us. -fn build_impl_generics( - builder: &aster::AstBuilder, - item: &Item, -) -> ast::Generics { +fn build_impl_generics(item: &Item) -> syn::Generics { let generics = bound::without_defaults(item.generics); let generics = bound::with_where_predicates_from_fields( - builder, item, &generics, + item, &generics, |attrs| attrs.ser_bound()); match item.attrs.ser_bound() { Some(predicates) => { - bound::with_where_predicates(builder, &generics, predicates) + bound::with_where_predicates(&generics, predicates) } None => { - bound::with_bound(builder, item, &generics, + bound::with_bound(item, &generics, needs_serialize_bound, - &builder.path().ids(&["_serde", "ser", "Serialize"]).build()) + &aster::path().ids(&["_serde", "ser", "Serialize"]).build()) } } } @@ -113,18 +70,14 @@ fn needs_serialize_bound(attrs: &attr::Field) -> bool { } fn serialize_body( - cx: &ExtCtxt, - builder: &aster::AstBuilder, item: &Item, - impl_generics: &ast::Generics, - ty: P, -) -> P { + impl_generics: &syn::Generics, + ty: syn::Ty, +) -> Tokens { match item.body { Body::Enum(ref variants) => { serialize_item_enum( - cx, - builder, - item.ident, + &item.ident, impl_generics, ty, variants, @@ -132,12 +85,10 @@ fn serialize_body( } Body::Struct(Style::Struct, ref fields) => { if fields.iter().any(|field| field.ident.is_none()) { - cx.span_bug(item.span, "struct has unnamed fields") + panic!("struct has unnamed fields"); } serialize_struct( - cx, - builder, impl_generics, ty, fields, @@ -145,12 +96,10 @@ fn serialize_body( } Body::Struct(Style::Tuple, ref fields) => { if fields.iter().any(|field| field.ident.is_some()) { - cx.span_bug(item.span, "tuple struct has named fields") + panic!("tuple struct has named fields"); } serialize_tuple_struct( - cx, - builder, impl_generics, ty, fields, @@ -158,8 +107,6 @@ fn serialize_body( } Body::Struct(Style::Newtype, ref fields) => { serialize_newtype_struct( - cx, - builder, impl_generics, ty, &fields[0], @@ -167,136 +114,116 @@ fn serialize_body( } Body::Struct(Style::Unit, _) => { serialize_unit_struct( - cx, - builder, &item.attrs) } } } -fn serialize_unit_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item_attrs: &attr::Item, -) -> P { - let type_name = name_expr(builder, item_attrs.name()); +fn serialize_unit_struct(item_attrs: &attr::Item) -> Tokens { + let type_name = item_attrs.name().serialize_name(); - quote_block!(cx, { - _serializer.serialize_unit_struct($type_name) - }).unwrap() + quote! { + _serializer.serialize_unit_struct(#type_name) + } } fn serialize_newtype_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - impl_generics: &ast::Generics, - item_ty: P, + impl_generics: &syn::Generics, + item_ty: syn::Ty, field: &Field, item_attrs: &attr::Item, -) -> P { - let type_name = name_expr(builder, item_attrs.name()); +) -> Tokens { + let type_name = item_attrs.name().serialize_name(); - let mut field_expr = quote_expr!(cx, &self.0); + let mut field_expr = quote!(&self.0); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(cx, builder, + field_expr = wrap_serialize_with( &item_ty, impl_generics, &field.ty, path, field_expr); } - quote_block!(cx, { - _serializer.serialize_newtype_struct($type_name, $field_expr) - }).unwrap() + quote! { + _serializer.serialize_newtype_struct(#type_name, #field_expr) + } } fn serialize_tuple_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - impl_generics: &ast::Generics, - ty: P, + impl_generics: &syn::Generics, + ty: syn::Ty, fields: &[Field], item_attrs: &attr::Item, -) -> P { +) -> Tokens { let serialize_stmts = serialize_tuple_struct_visitor( - cx, - builder, ty.clone(), fields, impl_generics, false, - cx.ident_of("serialize_tuple_struct_elt"), + aster::id("serialize_tuple_struct_elt"), ); - let type_name = name_expr(builder, item_attrs.name()); + let type_name = item_attrs.name().serialize_name(); let len = serialize_stmts.len(); - let let_mut = mut_if(cx, len > 0); + let let_mut = mut_if(len > 0); - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); - $serialize_stmts + quote! { + let #let_mut state = try!(_serializer.serialize_tuple_struct(#type_name, #len)); + #(serialize_stmts)* _serializer.serialize_tuple_struct_end(state) - }).unwrap() + } } fn serialize_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - impl_generics: &ast::Generics, - ty: P, + impl_generics: &syn::Generics, + ty: syn::Ty, fields: &[Field], item_attrs: &attr::Item, -) -> P { +) -> Tokens { let serialize_fields = serialize_struct_visitor( - cx, - builder, ty.clone(), fields, impl_generics, false, - cx.ident_of("serialize_struct_elt"), + aster::id("serialize_struct_elt"), ); - let type_name = name_expr(builder, item_attrs.name()); + let type_name = item_attrs.name().serialize_name(); let mut serialized_fields = fields.iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); - let let_mut = mut_if(cx, serialized_fields.peek().is_some()); + let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|field| { - let ident = field.ident.expect("struct has unnamed fields"); - let field_expr = quote_expr!(cx, &self.$ident); + let ident = field.ident.clone().expect("struct has unnamed fields"); + let field_expr = quote!(&self.#ident); match field.attrs.skip_serializing_if() { - Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }), - None => quote_expr!(cx, 1), + Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }), + None => quote!(1), } }) - .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); + .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_struct($type_name, $len)); - $serialize_fields + quote! { + let #let_mut state = try!(_serializer.serialize_struct(#type_name, #len)); + #(serialize_fields)* _serializer.serialize_struct_end(state) - }).unwrap() + } } fn serialize_item_enum( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - impl_generics: &ast::Generics, - ty: P, + type_ident: &syn::Ident, + impl_generics: &syn::Generics, + ty: syn::Ty, variants: &[Variant], item_attrs: &attr::Item, -) -> P { +) -> Tokens { let arms: Vec<_> = variants.iter() .enumerate() .map(|(variant_index, variant)| { serialize_variant( - cx, - builder, type_ident, impl_generics, ty.clone(), @@ -307,44 +234,40 @@ fn serialize_item_enum( }) .collect(); - quote_block!(cx, { + quote! { match *self { - $arms + #(arms)* } - }).unwrap() + } } fn serialize_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - generics: &ast::Generics, - ty: P, + type_ident: &syn::Ident, + generics: &syn::Generics, + ty: syn::Ty, variant: &Variant, variant_index: usize, item_attrs: &attr::Item, -) -> ast::Arm { - let type_name = name_expr(builder, item_attrs.name()); +) -> Tokens { + let type_name = item_attrs.name().serialize_name(); - let variant_ident = variant.ident; - let variant_name = name_expr(builder, variant.attrs.name()); + let variant_ident = variant.ident.clone(); + let variant_name = variant.attrs.name().serialize_name(); match variant.style { Style::Unit => { - quote_arm!(cx, - $type_ident::$variant_ident => + quote! { + #type_ident::#variant_ident => _serde::ser::Serializer::serialize_unit_variant( _serializer, - $type_name, - $variant_index, - $variant_name, + #type_name, + #variant_index, + #variant_name, ), - ) + } }, Style::Newtype => { let block = serialize_newtype_variant( - cx, - builder, type_name, variant_index, variant_name, @@ -353,26 +276,21 @@ fn serialize_variant( &variant.fields[0], ); - quote_arm!(cx, - $type_ident::$variant_ident(ref __simple_value) => $block - ) + quote! { + #type_ident::#variant_ident(ref __simple_value) => #block, + } }, Style::Tuple => { - let field_names: Vec = (0 .. variant.fields.len()) - .map(|i| builder.id(format!("__field{}", i))) + let field_names: Vec = (0 .. variant.fields.len()) + .map(|i| { + let id = aster::id(format!("__field{}", i)); + quote!(ref #id) + }) .collect(); - let pat = builder.pat().enum_() - .id(type_ident).id(variant_ident).build() - .with_pats( - field_names.iter() - .map(|field| builder.pat().ref_id(field)) - ) - .build(); + let pat = quote!(#type_ident::#variant_ident(#(field_names),*)); let block = serialize_tuple_variant( - cx, - builder, type_name, variant_index, variant_name, @@ -381,28 +299,21 @@ fn serialize_variant( &variant.fields, ); - quote_arm!(cx, - $pat => $block - ) + quote! { + #pat => { #block } + } } Style::Struct => { - let mut pat = builder.pat().struct_().id(type_ident).id(variant_ident).build(); - for field in &variant.fields { - let name = match field.ident { - Some(name) => name, - None => cx.span_bug(field.span, "struct variant has unnamed fields"), + let fields = variant.fields.iter().map(|field| { + let id = match field.ident { + Some(ref name) => name.clone(), + None => panic!("struct variant has unnamed fields"), }; - pat = pat.with_field_pat(ast::FieldPat { - ident: name, - pat: builder.pat().ref_id(name), - is_shorthand: true, - }); - } - let pat = pat.build(); + quote!(ref #id) + }); + let pat = quote!(#type_ident::#variant_ident { #(fields),* }); let block = serialize_struct_variant( - cx, - builder, variant_index, variant_name, generics, @@ -411,250 +322,228 @@ fn serialize_variant( item_attrs, ); - quote_arm!(cx, - $pat => $block - ) + quote! { + #pat => { #block } + } } } } fn serialize_newtype_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_name: P, + type_name: String, variant_index: usize, - variant_name: P, - item_ty: P, - generics: &ast::Generics, + variant_name: String, + item_ty: syn::Ty, + generics: &syn::Generics, field: &Field, -) -> P { - let mut field_expr = quote_expr!(cx, __simple_value); +) -> Tokens { + let mut field_expr = quote!(__simple_value); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(cx, builder, + field_expr = wrap_serialize_with( &item_ty, generics, &field.ty, path, field_expr); } - quote_block!(cx, { + quote! { _serde::ser::Serializer::serialize_newtype_variant( _serializer, - $type_name, - $variant_index, - $variant_name, - $field_expr, + #type_name, + #variant_index, + #variant_name, + #field_expr, ) - }).unwrap() + } } fn serialize_tuple_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_name: P, + type_name: String, variant_index: usize, - variant_name: P, - generics: &ast::Generics, - structure_ty: P, + variant_name: String, + generics: &syn::Generics, + structure_ty: syn::Ty, fields: &[Field], -) -> P { +) -> Tokens { let serialize_stmts = serialize_tuple_struct_visitor( - cx, - builder, structure_ty, fields, generics, true, - cx.ident_of("serialize_tuple_variant_elt"), + aster::id("serialize_tuple_variant_elt"), ); let len = serialize_stmts.len(); - let let_mut = mut_if(cx, len > 0); + let let_mut = mut_if(len > 0); - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); - $serialize_stmts + quote! { + let #let_mut state = try!(_serializer.serialize_tuple_variant(#type_name, #variant_index, #variant_name, #len)); + #(serialize_stmts)* _serializer.serialize_tuple_variant_end(state) - }).unwrap() + } } fn serialize_struct_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, variant_index: usize, - variant_name: P, - generics: &ast::Generics, - ty: P, + variant_name: String, + generics: &syn::Generics, + ty: syn::Ty, fields: &[Field], item_attrs: &attr::Item, -) -> P { - +) -> Tokens { let serialize_fields = serialize_struct_visitor( - cx, - builder, ty.clone(), fields, &generics, true, - cx.ident_of("serialize_struct_variant_elt"), + aster::id("serialize_struct_variant_elt"), ); - let item_name = name_expr(builder, item_attrs.name()); + let item_name = item_attrs.name().serialize_name(); let mut serialized_fields = fields.iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); - let let_mut = mut_if(cx, serialized_fields.peek().is_some()); + let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|field| { - let ident = field.ident.expect("struct has unnamed fields"); - let field_expr = quote_expr!(cx, $ident); + let ident = field.ident.clone().expect("struct has unnamed fields"); match field.attrs.skip_serializing_if() { - Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }), - None => quote_expr!(cx, 1), + Some(path) => quote!(if #path(#ident) { 0 } else { 1 }), + None => quote!(1), } }) - .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); + .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_struct_variant( - $item_name, - $variant_index, - $variant_name, - $len, + quote! { + let #let_mut state = try!(_serializer.serialize_struct_variant( + #item_name, + #variant_index, + #variant_name, + #len, )); - $serialize_fields + #(serialize_fields)* _serializer.serialize_struct_variant_end(state) - }).unwrap() + } } fn serialize_tuple_struct_visitor( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - structure_ty: P, + structure_ty: syn::Ty, fields: &[Field], - generics: &ast::Generics, + generics: &syn::Generics, is_enum: bool, - func: ast::Ident, -) -> Vec { + func: syn::Ident, +) -> Vec { fields.iter() .enumerate() .map(|(i, field)| { let mut field_expr = if is_enum { - builder.expr().path().id(format!("__field{}", i)).build() + let id = aster::id(format!("__field{}", i)); + quote!(#id) } else { - builder.expr().ref_().tup_field(i).self_() + quote!(&self.#i) }; let skip = field.attrs.skip_serializing_if() - .map(|path| quote_expr!(cx, $path($field_expr))); + .map(|path| quote!(#path(#field_expr))); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(cx, builder, + field_expr = wrap_serialize_with( &structure_ty, generics, &field.ty, path, field_expr); } - let ser = quote_expr!(cx, - try!(_serializer.$func(&mut state, $field_expr)); - ); + let ser = quote! { + try!(_serializer.#func(&mut state, #field_expr)); + }; match skip { - None => quote_stmt!(cx, $ser).unwrap(), - Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(), + None => ser, + Some(skip) => quote!(if !#skip { #ser }), } }) .collect() } fn serialize_struct_visitor( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - structure_ty: P, + structure_ty: syn::Ty, fields: &[Field], - generics: &ast::Generics, + generics: &syn::Generics, is_enum: bool, - func: ast::Ident, -) -> Vec { + func: syn::Ident, +) -> Vec { fields.iter() .filter(|&field| !field.attrs.skip_serializing()) .map(|field| { - let ident = field.ident.expect("struct has unnamed field"); + let ident = field.ident.clone().expect("struct has unnamed field"); let mut field_expr = if is_enum { - quote_expr!(cx, $ident) + quote!(#ident) } else { - quote_expr!(cx, &self.$ident) + quote!(&self.#ident) }; - let key_expr = name_expr(builder, field.attrs.name()); + let key_expr = field.attrs.name().serialize_name(); let skip = field.attrs.skip_serializing_if() - .map(|path| quote_expr!(cx, $path($field_expr))); + .map(|path| quote!(#path(#field_expr))); if let Some(path) = field.attrs.serialize_with() { - field_expr = wrap_serialize_with(cx, builder, + field_expr = wrap_serialize_with( &structure_ty, generics, &field.ty, path, field_expr) } - let ser = quote_expr!(cx, - try!(_serializer.$func(&mut state, $key_expr, $field_expr)); - ); + let ser = quote! { + try!(_serializer.#func(&mut state, #key_expr, #field_expr)); + }; match skip { - None => quote_stmt!(cx, $ser).unwrap(), - Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(), + None => ser, + Some(skip) => quote!(if !#skip { #ser }), } }) .collect() } fn wrap_serialize_with( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item_ty: &P, - generics: &ast::Generics, - field_ty: &P, - path: &ast::Path, - value: P, -) -> P { + item_ty: &syn::Ty, + generics: &syn::Generics, + field_ty: &syn::Ty, + path: &syn::Path, + value: Tokens, +) -> Tokens { let where_clause = &generics.where_clause; - let wrapper_generics = builder.from_generics(generics.clone()) + let wrapper_generics = aster::from_generics(generics.clone()) .add_lifetime_bound("'__a") .lifetime_name("'__a") .build(); - let wrapper_ty = builder.path() + let wrapper_ty = aster::path() .segment("__SerializeWith") .with_generics(wrapper_generics.clone()) .build() .build(); - quote_expr!(cx, { - struct __SerializeWith $wrapper_generics $where_clause { - value: &'__a $field_ty, - phantom: ::std::marker::PhantomData<$item_ty>, - } + quote! { + { + struct __SerializeWith #wrapper_generics #where_clause { + value: &'__a #field_ty, + phantom: ::std::marker::PhantomData<#item_ty>, + } - impl $wrapper_generics _serde::ser::Serialize for $wrapper_ty $where_clause { - fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error> - where __S: _serde::ser::Serializer - { - $path(self.value, __s) + impl #wrapper_generics _serde::ser::Serialize for #wrapper_ty #where_clause { + fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error> + where __S: _serde::ser::Serializer + { + #path(self.value, __s) + } + } + + __SerializeWith { + value: #value, + phantom: ::std::marker::PhantomData::<#item_ty>, } } - - __SerializeWith { - value: $value, - phantom: ::std::marker::PhantomData::<$item_ty>, - } - }) -} - -fn name_expr( - builder: &aster::AstBuilder, - name: &attr::Name, -) -> P { - builder.expr().str(name.serialize_name()) + } } // Serialization of an empty struct results in code like: @@ -663,10 +552,10 @@ fn name_expr( // serializer.serialize_struct_end(state) // // where we want to omit the `mut` to avoid a warning. -fn mut_if(cx: &ExtCtxt, is_mut: bool) -> Vec { +fn mut_if(is_mut: bool) -> Option { if is_mut { - quote_tokens!(cx, mut) + Some(quote!(mut)) } else { - Vec::new() + None } } diff --git a/serde_codegen/src/span.rs b/serde_codegen/src/span.rs deleted file mode 100644 index 5421868d..00000000 --- a/serde_codegen/src/span.rs +++ /dev/null @@ -1,43 +0,0 @@ -use syntax::ast; -use syntax::codemap::{self, ExpnId, Span}; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::fold::{self, Folder}; -use syntax::parse::token::intern; -use syntax::ptr::P; - -pub fn record_expansion( - cx: &ExtCtxt, - item: P, - derive: &str, -) -> Annotatable { - let info = codemap::ExpnInfo { - call_site: codemap::DUMMY_SP, - callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(intern(&format!("derive({})", derive))), - span: None, - allow_internal_unstable: false, - }, - }; - let expn_id = cx.codemap().record_expansion(info); - - let mut respanner = Respanner { expn_id: expn_id }; - let item = item.map(|item| respanner.fold_item_simple(item)); - Annotatable::Item(item) -} - -struct Respanner { - expn_id: ExpnId, -} - -impl Folder for Respanner { - fn new_span(&mut self, span: Span) -> Span { - Span { - expn_id: self.expn_id, - .. span - } - } - - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } -} diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 3219579d..2a621f1f 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -11,11 +11,8 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [features] -default = ["with-syntex"] unstable-testing = ["clippy"] -with-syntex = ["syntex_syntax", "syntex_errors"] [dependencies] clippy = { version = "^0.*", optional = true } -syntex_syntax = { version = "^0.43.0", optional = true } -syntex_errors = { version = "^0.43.0", optional = true } +syn = "0.5" diff --git a/serde_codegen_internals/src/ast.rs b/serde_codegen_internals/src/ast.rs index dd79944f..d62ad807 100644 --- a/serde_codegen_internals/src/ast.rs +++ b/serde_codegen_internals/src/ast.rs @@ -1,17 +1,12 @@ -use syntax::ast; -use syntax::codemap; -use syntax::ext::base::ExtCtxt; -use syntax::ptr::P; - +use syn; use attr; -use Error; +use Ctxt; pub struct Item<'a> { - pub ident: ast::Ident, - pub span: codemap::Span, + pub ident: syn::Ident, pub attrs: attr::Item, pub body: Body<'a>, - pub generics: &'a ast::Generics, + pub generics: &'a syn::Generics, } pub enum Body<'a> { @@ -20,18 +15,16 @@ pub enum Body<'a> { } pub struct Variant<'a> { - pub ident: ast::Ident, - pub span: codemap::Span, + pub ident: syn::Ident, pub attrs: attr::Variant, pub style: Style, pub fields: Vec>, } pub struct Field<'a> { - pub ident: Option, - pub span: codemap::Span, + pub ident: Option, pub attrs: attr::Field, - pub ty: &'a P, + pub ty: &'a syn::Ty, } pub enum Style { @@ -42,33 +35,25 @@ pub enum Style { } impl<'a> Item<'a> { - pub fn from_ast( - cx: &ExtCtxt, - item: &'a ast::Item, - ) -> Result, Error> { + pub fn from_ast(cx: &Ctxt, item: &'a syn::Item) -> Item<'a> { let attrs = attr::Item::from_ast(cx, item); - let (body, generics) = match item.node { - ast::ItemKind::Enum(ref enum_def, ref generics) => { - let variants = enum_from_ast(cx, enum_def); - (Body::Enum(variants), generics) + let body = match item.body { + syn::Body::Enum(ref variants) => { + Body::Enum(enum_from_ast(cx, variants)) } - ast::ItemKind::Struct(ref variant_data, ref generics) => { + syn::Body::Struct(ref variant_data) => { let (style, fields) = struct_from_ast(cx, variant_data); - (Body::Struct(style, fields), generics) - } - _ => { - return Err(Error::UnexpectedItemKind); + Body::Struct(style, fields) } }; - Ok(Item { - ident: item.ident, - span: item.span, + Item { + ident: item.ident.clone(), attrs: attrs, body: body, - generics: generics, - }) + generics: &item.generics, + } } } @@ -86,16 +71,12 @@ impl<'a> Body<'a> { } } -fn enum_from_ast<'a>( - cx: &ExtCtxt, - enum_def: &'a ast::EnumDef, -) -> Vec> { - enum_def.variants.iter() +fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec> { + variants.iter() .map(|variant| { - let (style, fields) = struct_from_ast(cx, &variant.node.data); + let (style, fields) = struct_from_ast(cx, &variant.data); Variant { - ident: variant.node.name, - span: variant.span, + ident: variant.ident.clone(), attrs: attr::Variant::from_ast(cx, variant), style: style, fields: fields, @@ -104,36 +85,29 @@ fn enum_from_ast<'a>( .collect() } -fn struct_from_ast<'a>( - cx: &ExtCtxt, - variant_data: &'a ast::VariantData, -) -> (Style, Vec>) { - match *variant_data { - ast::VariantData::Struct(ref fields, _) => { +fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec>) { + match *data { + syn::VariantData::Struct(ref fields) => { (Style::Struct, fields_from_ast(cx, fields)) } - ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => { + syn::VariantData::Tuple(ref fields) if fields.len() == 1 => { (Style::Newtype, fields_from_ast(cx, fields)) } - ast::VariantData::Tuple(ref fields, _) => { + syn::VariantData::Tuple(ref fields) => { (Style::Tuple, fields_from_ast(cx, fields)) } - ast::VariantData::Unit(_) => { + syn::VariantData::Unit => { (Style::Unit, Vec::new()) } } } -fn fields_from_ast<'a>( - cx: &ExtCtxt, - fields: &'a [ast::StructField], -) -> Vec> { +fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec> { fields.iter() .enumerate() .map(|(i, field)| { Field { - ident: field.ident, - span: field.span, + ident: field.ident.clone(), attrs: attr::Field::from_ast(cx, i, field), ty: &field.ty, } diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index a4dd2ce3..02b72b6c 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -1,15 +1,5 @@ -use std::rc::Rc; - -use syntax::ast; -use syntax::attr::{self, HasAttrs}; -use syntax::codemap::{Span, Spanned, respan}; -use syntax::ext::base::ExtCtxt; -use syntax::fold::Folder; -use syntax::parse::parser::{Parser, PathStyle}; -use syntax::parse::token::{self, InternedString}; -use syntax::parse; -use syntax::print::pprust::{lit_to_string, meta_item_to_string, meta_list_item_to_string}; -use syntax::tokenstream::{self, TokenTree}; +use Ctxt; +use syn::{self, Ident}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints // are `attr::Item::from_ast`, `attr::Variant::from_ast`, and @@ -19,13 +9,14 @@ use syntax::tokenstream::{self, TokenTree}; // user will see errors simultaneously for all bad attributes in the crate // rather than just the first. -struct Attr<'a, 'b: 'a, T> { - cx: &'a ExtCtxt<'b>, +struct Attr<'c, T> { + cx: &'c Ctxt, name: &'static str, - value: Option>, + value: Option, } -impl<'a, 'b, T> Attr<'a, 'b, T> { - fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self { + +impl<'c, T> Attr<'c, T> { + fn none(cx: &'c Ctxt, name: &'static str) -> Self { Attr { cx: cx, name: name, @@ -33,47 +24,40 @@ impl<'a, 'b, T> Attr<'a, 'b, T> { } } - fn set(&mut self, span: Span, t: T) { - if let Some(Spanned { span: prev_span, .. }) = self.value { - let mut err = self.cx.struct_span_err( - span, - &format!("duplicate serde attribute `{}`", self.name)); - err.span_help(prev_span, "previously set here"); - err.emit(); + fn set(&mut self, value: T) { + if self.value.is_some() { + self.cx.error(format!("duplicate serde attribute `{}`", self.name)); } else { - self.value = Some(respan(span, t)); + self.value = Some(value); } } - fn set_opt(&mut self, v: Option>) { - if let Some(v) = v { - self.set(v.span, v.node); + fn set_opt(&mut self, value: Option) { + if let Some(value) = value { + self.set(value); } } - fn set_if_none(&mut self, span: Span, t: T) { + fn set_if_none(&mut self, value: T) { if self.value.is_none() { - self.value = Some(respan(span, t)); + self.value = Some(value); } } fn get(self) -> Option { - self.value.map(|spanned| spanned.node) - } - - fn get_spanned(self) -> Option> { self.value } } -struct BoolAttr<'a, 'b: 'a>(Attr<'a, 'b, ()>); -impl<'a, 'b> BoolAttr<'a, 'b> { - fn none(cx: &'a ExtCtxt<'b>, name: &'static str) -> Self { +struct BoolAttr<'c>(Attr<'c, ()>); + +impl<'c> BoolAttr<'c> { + fn none(cx: &'c Ctxt, name: &'static str) -> Self { BoolAttr(Attr::none(cx, name)) } - fn set_true(&mut self, span: Span) { - self.0.set(span, ()); + fn set_true(&mut self) { + self.0.set(()); } fn get(&self) -> bool { @@ -83,18 +67,18 @@ impl<'a, 'b> BoolAttr<'a, 'b> { #[derive(Debug)] pub struct Name { - serialize: InternedString, - deserialize: InternedString, + serialize: String, + deserialize: String, } impl Name { /// Return the container name for the container when serializing. - pub fn serialize_name(&self) -> InternedString { + pub fn serialize_name(&self) -> String { self.serialize.clone() } /// Return the container name for the container when deserializing. - pub fn deserialize_name(&self) -> InternedString { + pub fn deserialize_name(&self) -> String { self.deserialize.clone() } } @@ -104,35 +88,30 @@ impl Name { pub struct Item { name: Name, deny_unknown_fields: bool, - ser_bound: Option>, - de_bound: Option>, + ser_bound: Option>, + de_bound: Option>, } impl Item { /// Extract out the `#[serde(...)]` attributes from an item. - pub fn from_ast(cx: &ExtCtxt, item: &ast::Item) -> Self { + pub fn from_ast(cx: &Ctxt, item: &syn::Item) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields"); let mut ser_bound = Attr::none(cx, "bound"); let mut de_bound = Attr::none(cx, "bound"); - let ident = item.ident.name.as_str(); - - for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) { + for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { - let span = meta_item.span; - match meta_item.node { + match meta_item { // Parse `#[serde(rename="foo")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => { - if let Ok(s) = get_str_from_lit(cx, name, lit) { - ser_name.set(span, s.clone()); - de_name.set(span, s); - } + syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { + ser_name.set(lit.clone()); + de_name.set(lit.clone()); } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => { + syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -140,20 +119,20 @@ impl Item { } // Parse `#[serde(deny_unknown_fields)]` - ast::MetaItemKind::Word(ref name) if name == &"deny_unknown_fields" => { - deny_unknown_fields.set_true(span); + syn::MetaItem::Word(ref name) if name == "deny_unknown_fields" => { + deny_unknown_fields.set_true(); } // Parse `#[serde(bound="D: Serialize")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => { + syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) { - ser_bound.set(span, where_predicates.clone()); - de_bound.set(span, where_predicates); + ser_bound.set(where_predicates.clone()); + de_bound.set(where_predicates); } } // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` - ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => { + syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); de_bound.set_opt(de); @@ -161,10 +140,8 @@ impl Item { } _ => { - cx.span_err( - meta_item.span, - &format!("unknown serde container attribute `{}`", - meta_item_to_string(&meta_item))); + // TODO include name of attr + cx.error("unknown serde container attribute"); } } } @@ -172,8 +149,8 @@ impl Item { Item { name: Name { - serialize: ser_name.get().unwrap_or(ident.clone()), - deserialize: de_name.get().unwrap_or(ident), + serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), + deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()), }, deny_unknown_fields: deny_unknown_fields.get(), ser_bound: ser_bound.get(), @@ -189,11 +166,11 @@ impl Item { self.deny_unknown_fields } - pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> { + pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } - pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> { + pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } } @@ -205,26 +182,21 @@ pub struct Variant { } impl Variant { - pub fn from_ast(cx: &ExtCtxt, variant: &ast::Variant) -> Self { + pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); - let ident = variant.node.name.name.as_str(); - - for meta_items in variant.node.attrs.iter().filter_map(get_serde_meta_items) { + for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { - let span = meta_item.span; - match meta_item.node { + match meta_item { // Parse `#[serde(rename="foo")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => { - if let Ok(s) = get_str_from_lit(cx, name, lit) { - ser_name.set(span, s.clone()); - de_name.set(span, s); - } + syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { + ser_name.set(lit.clone()); + de_name.set(lit.clone()); } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => { + syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -232,10 +204,8 @@ impl Variant { } _ => { - cx.span_err( - meta_item.span, - &format!("unknown serde variant attribute `{}`", - meta_item_to_string(&meta_item))); + // TODO include attribute + cx.error("unknown serde variant attribute"); } } } @@ -243,8 +213,8 @@ impl Variant { Variant { name: Name { - serialize: ser_name.get().unwrap_or(ident.clone()), - deserialize: de_name.get().unwrap_or(ident), + serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()), + deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()), }, } } @@ -260,12 +230,12 @@ pub struct Field { name: Name, skip_serializing: bool, skip_deserializing: bool, - skip_serializing_if: Option, + skip_serializing_if: Option, default: FieldDefault, - serialize_with: Option, - deserialize_with: Option, - ser_bound: Option>, - de_bound: Option>, + serialize_with: Option, + deserialize_with: Option, + ser_bound: Option>, + de_bound: Option>, } /// Represents the default to use for a field when deserializing. @@ -276,14 +246,14 @@ pub enum FieldDefault { /// The default is given by `std::default::Default::default()`. Default, /// The default is given by this function. - Path(ast::Path), + Path(syn::Path), } impl Field { /// Extract out the `#[serde(...)]` attributes from a struct field. - pub fn from_ast(cx: &ExtCtxt, + pub fn from_ast(cx: &Ctxt, index: usize, - field: &ast::StructField) -> Self { + field: &syn::Field) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); @@ -296,24 +266,21 @@ impl Field { let mut de_bound = Attr::none(cx, "bound"); let ident = match field.ident { - Some(ident) => ident.name.as_str(), - None => token::intern_and_get_ident(&index.to_string()), + Some(ref ident) => ident.to_string(), + None => index.to_string(), }; for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { - let span = meta_item.span; - match meta_item.node { + match meta_item { // Parse `#[serde(rename="foo")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"rename" => { - if let Ok(s) = get_str_from_lit(cx, name, lit) { - ser_name.set(span, s.clone()); - de_name.set(span, s); - } + syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { + ser_name.set(lit.clone()); + de_name.set(lit.clone()); } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - ast::MetaItemKind::List(ref name, ref meta_items) if name == &"rename" => { + syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -321,58 +288,58 @@ impl Field { } // Parse `#[serde(default)]` - ast::MetaItemKind::Word(ref name) if name == &"default" => { - default.set(span, FieldDefault::Default); + syn::MetaItem::Word(ref name) if name == "default" => { + default.set(FieldDefault::Default); } // Parse `#[serde(default="...")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"default" => { + syn::MetaItem::NameValue(ref name, ref lit) if name == "default" => { if let Ok(path) = parse_lit_into_path(cx, name, lit) { - default.set(span, FieldDefault::Path(path)); + default.set(FieldDefault::Path(path)); } } // Parse `#[serde(skip_serializing)]` - ast::MetaItemKind::Word(ref name) if name == &"skip_serializing" => { - skip_serializing.set_true(span); + syn::MetaItem::Word(ref name) if name == "skip_serializing" => { + skip_serializing.set_true(); } // Parse `#[serde(skip_deserializing)]` - ast::MetaItemKind::Word(ref name) if name == &"skip_deserializing" => { - skip_deserializing.set_true(span); + syn::MetaItem::Word(ref name) if name == "skip_deserializing" => { + skip_deserializing.set_true(); } // Parse `#[serde(skip_serializing_if="...")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"skip_serializing_if" => { + syn::MetaItem::NameValue(ref name, ref lit) if name == "skip_serializing_if" => { if let Ok(path) = parse_lit_into_path(cx, name, lit) { - skip_serializing_if.set(span, path); + skip_serializing_if.set(path); } } // Parse `#[serde(serialize_with="...")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize_with" => { + syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name, lit) { - serialize_with.set(span, path); + serialize_with.set(path); } } // Parse `#[serde(deserialize_with="...")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize_with" => { + syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name, lit) { - deserialize_with.set(span, path); + deserialize_with.set(path); } } // Parse `#[serde(bound="D: Serialize")]` - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => { + syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) { - ser_bound.set(span, where_predicates.clone()); - de_bound.set(span, where_predicates); + ser_bound.set(where_predicates.clone()); + de_bound.set(where_predicates); } } // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` - ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => { + syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); de_bound.set_opt(de); @@ -380,10 +347,8 @@ impl Field { } _ => { - cx.span_err( - meta_item.span, - &format!("unknown serde field attribute `{}`", - meta_item_to_string(&meta_item))); + // TODO include attribute + cx.error("unknown serde field attribute"); } } } @@ -391,8 +356,8 @@ impl Field { // Is skip_deserializing, initialize the field to Default::default() // unless a different default is specified by `#[serde(default="...")]` - if let Some(Spanned { span, .. }) = skip_deserializing.0.value { - default.set_if_none(span, FieldDefault::Default); + if skip_deserializing.0.value.is_some() { + default.set_if_none(FieldDefault::Default); } Field { @@ -423,7 +388,7 @@ impl Field { self.skip_deserializing } - pub fn skip_serializing_if(&self) -> Option<&ast::Path> { + pub fn skip_serializing_if(&self) -> Option<&syn::Path> { self.skip_serializing_if.as_ref() } @@ -431,230 +396,95 @@ impl Field { &self.default } - pub fn serialize_with(&self) -> Option<&ast::Path> { + pub fn serialize_with(&self) -> Option<&syn::Path> { self.serialize_with.as_ref() } - pub fn deserialize_with(&self) -> Option<&ast::Path> { + pub fn deserialize_with(&self) -> Option<&syn::Path> { self.deserialize_with.as_ref() } - pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> { + pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } - pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> { + pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } } -type SerAndDe = (Option>, Option>); +type SerAndDe = (Option, Option); fn get_ser_and_de( - cx: &ExtCtxt, + cx: &Ctxt, attribute: &'static str, - items: &[ast::NestedMetaItem], + items: &[syn::MetaItem], f: F ) -> Result, ()> - where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result, + where F: Fn(&Ctxt, &Ident, &str) -> Result, { let mut ser_item = Attr::none(cx, attribute); let mut de_item = Attr::none(cx, attribute); for item in items { - match item.node { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => { - match meta_item.node { - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => { - if let Ok(v) = f(cx, name, lit) { - ser_item.set(item.span, v); - } - } + match *item { + syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize" => { + if let Ok(v) = f(cx, name, lit) { + ser_item.set(v); + } + } - ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => { - if let Ok(v) = f(cx, name, lit) { - de_item.set(item.span, v); - } - } - - _ => { - cx.span_err( - item.span, - &format!("unknown {} attribute `{}`", - attribute, - meta_item_to_string(meta_item))); - - return Err(()); - } + syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize" => { + if let Ok(v) = f(cx, name, lit) { + de_item.set(v); } } _ => { - cx.span_err( - item.span, - &format!("unknown {} attribute `{}`", - attribute, - meta_list_item_to_string(item))); - + cx.error(format!("bad {} attribute", attribute)); return Err(()); } } } - Ok((ser_item.get_spanned(), de_item.get_spanned())) + Ok((ser_item.get(), de_item.get())) } fn get_renames( - cx: &ExtCtxt, - items: &[ast::NestedMetaItem], -) -> Result, ()> { - get_ser_and_de(cx, "rename", items, get_str_from_lit) + cx: &Ctxt, + items: &[syn::MetaItem], +) -> Result, ()> { + get_ser_and_de(cx, "rename", items, |_, _, s| Ok(s.to_owned())) } fn get_where_predicates( - cx: &ExtCtxt, - items: &[ast::NestedMetaItem], -) -> Result>, ()> { + cx: &Ctxt, + items: &[syn::MetaItem], +) -> Result>, ()> { get_ser_and_de(cx, "bound", items, parse_lit_into_where) } -pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option> { - match attr.node.value.node { - ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => { - attr::mark_used(attr); - Some(items.iter().filter_map(|item| { - match item.node { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => { - Some((*meta_item.clone()).clone()) - } - _ => None, - } - }).collect()) +pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> { + match attr.value { + syn::MetaItem::List(ref name, ref items) if name == "serde" => { + Some(items.iter().cloned().collect()) } _ => None } } -/// This syntax folder rewrites tokens to say their spans are coming from a macro context. -struct Respanner<'a, 'b: 'a> { - cx: &'a ExtCtxt<'b>, +fn parse_lit_into_path(cx: &Ctxt, name: &Ident, lit: &str) -> Result { + // TODO handle error + Ok(syn::parse_path(lit).unwrap()) } -impl<'a, 'b> Folder for Respanner<'a, 'b> { - fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree { - match *tt { - TokenTree::Token(span, ref tok) => { - TokenTree::Token( - self.new_span(span), - self.fold_token(tok.clone()) - ) - } - TokenTree::Delimited(span, ref delimed) => { - TokenTree::Delimited( - self.new_span(span), - Rc::new(tokenstream::Delimited { - delim: delimed.delim, - open_span: delimed.open_span, - tts: self.fold_tts(&delimed.tts), - close_span: delimed.close_span, - }) - ) - } - TokenTree::Sequence(span, ref seq) => { - TokenTree::Sequence( - self.new_span(span), - Rc::new(tokenstream::SequenceRepetition { - tts: self.fold_tts(&seq.tts), - separator: seq.separator.clone().map(|tok| self.fold_token(tok)), - ..**seq - }) - ) - } - } - } - - fn new_span(&mut self, span: Span) -> Span { - Span { - lo: span.lo, - hi: span.hi, - expn_id: self.cx.backtrace(), - } - } -} - -fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result { - match lit.node { - ast::LitKind::Str(ref s, _) => Ok(s.clone()), - _ => { - cx.span_err( - lit.span, - &format!("serde annotation `{}` must be a string, not `{}`", - name, - lit_to_string(lit))); - - Err(()) - } - } -} - -// If we just parse a string literal from an attibute, any syntax errors in the -// source will only have spans that point inside the string and not back to the -// attribute. So to have better error reporting, we'll first parse the string -// into a token tree. Then we'll update those spans to say they're coming from a -// macro context that originally came from the attribnute, and then finally -// parse them into an expression or where-clause. -fn parse_string_via_tts(cx: &ExtCtxt, name: &str, string: String, action: F) -> Result - where F: for<'a> Fn(&'a mut Parser) -> parse::PResult<'a, T>, -{ - let tts = panictry!(parse::parse_tts_from_source_str( - format!("", name), - string, - cx.cfg(), - cx.parse_sess())); - - // Respan the spans to say they are all coming from this macro. - let tts = Respanner { cx: cx }.fold_tts(&tts); - - let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts); - - let path = match action(&mut parser) { - Ok(path) => path, - Err(mut e) => { - e.emit(); - return Err(()); - } - }; - - // Make sure to error out if there are trailing characters in the stream. - match parser.expect(&token::Eof) { - Ok(()) => { } - Err(mut e) => { - e.emit(); - return Err(()); - } - } - - Ok(path) -} - -fn parse_lit_into_path(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result { - let string = try!(get_str_from_lit(cx, name, lit)).to_string(); - - parse_string_via_tts(cx, name, string, |parser| { - parser.parse_path(PathStyle::Type) - }) -} - -fn parse_lit_into_where(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result, ()> { - let string = try!(get_str_from_lit(cx, name, lit)); - if string.is_empty() { +fn parse_lit_into_where(cx: &Ctxt, name: &Ident, lit: &str) -> Result, ()> { + if lit.is_empty() { return Ok(Vec::new()); } - let where_string = format!("where {}", string); + let where_string = format!("where {}", lit); - parse_string_via_tts(cx, name, where_string, |parser| { - let where_clause = try!(parser.parse_where_clause()); - Ok(where_clause.predicates) - }) + // TODO handle error + Ok(syn::parse_where_clause(&where_string).unwrap().predicates) } diff --git a/serde_codegen_internals/src/ctxt.rs b/serde_codegen_internals/src/ctxt.rs new file mode 100644 index 00000000..a516aec8 --- /dev/null +++ b/serde_codegen_internals/src/ctxt.rs @@ -0,0 +1,29 @@ +use std::fmt::Display; +use std::cell::Cell; + +#[derive(Default)] +pub struct Ctxt { + err_count: Cell, +} + +impl Ctxt { + pub fn new() -> Self { + Default::default() + } + + pub fn error(&self, msg: T) { + println!("{}", msg); + self.err_count.set(self.err_count.get() + 1); + } +} + +impl Drop for Ctxt { + fn drop(&mut self) { + let err_count = self.err_count.get(); + if err_count == 1 { + panic!("1 error"); + } else if err_count > 1 { + panic!("{} errors", err_count); + } + } +} diff --git a/serde_codegen_internals/src/error.rs b/serde_codegen_internals/src/error.rs deleted file mode 100644 index 08337c0b..00000000 --- a/serde_codegen_internals/src/error.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::error; -use std::fmt; - -#[derive(Debug)] -pub enum Error { - UnexpectedItemKind, -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "expected a struct or enum") - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - "expected a struct or enum" - } -} diff --git a/serde_codegen_internals/src/lib.rs b/serde_codegen_internals/src/lib.rs index 89f20aa6..0f37f5fa 100644 --- a/serde_codegen_internals/src/lib.rs +++ b/serde_codegen_internals/src/lib.rs @@ -1,21 +1,10 @@ #![cfg_attr(feature = "clippy", plugin(clippy))] #![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))] -#[cfg(feature = "with-syntex")] -#[macro_use] -extern crate syntex_syntax as syntax; -#[cfg(feature = "with-syntex")] -extern crate syntex_errors as errors; - -#[cfg(not(feature = "with-syntex"))] -#[macro_use] -extern crate syntax; -#[cfg(not(feature = "with-syntex"))] -extern crate rustc_errors as errors; +extern crate syn; pub mod ast; pub mod attr; -mod error; -pub use error::Error; +mod ctxt; +pub use ctxt::Ctxt; diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 66930b14..da38783d 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -14,8 +14,11 @@ include = ["Cargo.toml", "src/**/*.rs"] name = "serde_derive" rustc-macro = true -[dependencies] -serde_codegen = { version = "=0.8.8", path = "../serde_codegen" } +[dependencies.serde_codegen] +version = "=0.8.8" +path = "../serde_codegen" +default-features = false +features = ["with-syn"] [dev-dependencies] fnv = "1.0" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index aa7bba60..5c80708a 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -9,13 +9,13 @@ use rustc_macro::TokenStream; #[rustc_macro_derive(Serialize)] pub fn derive_serialize(input: TokenStream) -> TokenStream { let item = format!("#[derive(Serialize)]\n{}", input); - let expanded = serde_codegen::expand_str(&item).unwrap(); + let expanded = serde_codegen::expand_single_item(&item); expanded.parse().unwrap() } #[rustc_macro_derive(Deserialize)] pub fn derive_deserialize(input: TokenStream) -> TokenStream { let item = format!("#[derive(Deserialize)]\n{}", input); - let expanded = serde_codegen::expand_str(&item).unwrap(); + let expanded = serde_codegen::expand_single_item(&item); expanded.parse().unwrap() } From 55e5f194370d596ccafc1e12a917a9294b818c17 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 12 Sep 2016 00:04:21 -0700 Subject: [PATCH 027/111] Same for deserialization --- serde_codegen/src/de.rs | 987 +++++++++++++++++---------------------- serde_codegen/src/lib.rs | 82 ++-- 2 files changed, 475 insertions(+), 594 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index b630ede0..dae4ca65 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -1,112 +1,69 @@ -use aster; - -use syntax::ast::{self, Ident, MetaItem}; -use syntax::codemap::Span; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::parse::token::InternedString; -use syntax::ptr::P; -use syntax::tokenstream::TokenTree; +use syn::{self, aster}; +use quote::{self, Tokens}; use bound; -use span; use internals::ast::{Body, Field, Item, Style, Variant}; -use internals::{attr, Error}; +use internals::{self, attr}; -pub fn expand_derive_deserialize( - cx: &mut ExtCtxt, - span: Span, - meta_item: &MetaItem, - annotatable: &Annotatable, - push: &mut FnMut(Annotatable) -) { - let item = match *annotatable { - Annotatable::Item(ref item) => item, - _ => { - cx.span_err( - meta_item.span, - "`#[derive(Deserialize)]` may only be applied to structs and enums"); - return; - } +pub fn expand_derive_deserialize(item: &syn::Item) -> Tokens { + let item = { + let ctxt = internals::Ctxt::new(); + let item = Item::from_ast(&ctxt, item); + check_no_str(&ctxt, &item); + item }; - let item = match Item::from_ast(cx, item) { - Ok(item) => item, - Err(Error::UnexpectedItemKind) => { - cx.span_err(item.span, - "`#[derive(Deserialize)]` may only be applied to structs and enums"); - return; - } - }; + let impl_generics = build_impl_generics(&item); - if check_no_str(cx, &item).is_err() { - return; - } - - let builder = aster::AstBuilder::new().span(span); - - let impl_item = deserialize_item(cx, &builder, &item); - push(span::record_expansion(cx, impl_item, "Deserialize")) -} - -fn deserialize_item( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, -) -> P { - let impl_generics = build_impl_generics(builder, &item); - - let ty = builder.ty().path() - .segment(item.ident).with_generics(impl_generics.clone()).build() + let ty = aster::ty().path() + .segment(item.ident.clone()).with_generics(impl_generics.clone()).build() .build(); - let body = deserialize_body(cx, - builder, - &item, + let body = deserialize_body(&item, &impl_generics, ty.clone()); let where_clause = &impl_generics.where_clause; - let dummy_const = builder.id(format!("_IMPL_DESERIALIZE_FOR_{}", item.ident)); + let dummy_const = aster::id(format!("_IMPL_DESERIALIZE_FOR_{}", item.ident)); - quote_item!(cx, + quote! { #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const $dummy_const: () = { + const #dummy_const: () = { extern crate serde as _serde; #[automatically_derived] - impl $impl_generics _serde::de::Deserialize for $ty $where_clause { - fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<$ty, __D::Error> + impl #impl_generics _serde::de::Deserialize for #ty #where_clause { + fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<#ty, __D::Error> where __D: _serde::de::Deserializer - $body + { + #body + } } }; - ).unwrap() + } } // All the generics in the input, plus a bound `T: Deserialize` for each generic // field type that will be deserialized by us, plus a bound `T: Default` for // each generic field type that will be set to a default value. -fn build_impl_generics( - builder: &aster::AstBuilder, - item: &Item, -) -> ast::Generics { +fn build_impl_generics(item: &Item) -> syn::Generics { let generics = bound::without_defaults(item.generics); let generics = bound::with_where_predicates_from_fields( - builder, item, &generics, + item, &generics, |attrs| attrs.de_bound()); match item.attrs.de_bound() { Some(predicates) => { - bound::with_where_predicates(builder, &generics, predicates) + bound::with_where_predicates(&generics, predicates) } None => { - let generics = bound::with_bound(builder, item, &generics, + let generics = bound::with_bound(item, &generics, needs_deserialize_bound, - &builder.path().ids(&["_serde", "de", "Deserialize"]).build()); - let generics = bound::with_bound(builder, item, &generics, + &aster::path().ids(&["_serde", "de", "Deserialize"]).build()); + let generics = bound::with_bound(item, &generics, requires_default, - &builder.path().global().ids(&["std", "default", "Default"]).build()); + &aster::path().global().ids(&["std", "default", "Default"]).build()); generics } } @@ -129,18 +86,14 @@ fn requires_default(attrs: &attr::Field) -> bool { } fn deserialize_body( - cx: &ExtCtxt, - builder: &aster::AstBuilder, item: &Item, - impl_generics: &ast::Generics, - ty: P, -) -> P { + impl_generics: &syn::Generics, + ty: syn::Ty, +) -> Tokens { match item.body { Body::Enum(ref variants) => { deserialize_item_enum( - cx, - builder, - item.ident, + &item.ident, impl_generics, ty, variants, @@ -148,13 +101,11 @@ fn deserialize_body( } Body::Struct(Style::Struct, ref fields) => { if fields.iter().any(|field| field.ident.is_none()) { - cx.span_bug(item.span, "struct has unnamed fields") + panic!("struct has unnamed fields"); } deserialize_struct( - cx, - builder, - item.ident, + &item.ident, None, impl_generics, ty, @@ -164,13 +115,11 @@ fn deserialize_body( Body::Struct(Style::Tuple, ref fields) | Body::Struct(Style::Newtype, ref fields) => { if fields.iter().any(|field| field.ident.is_some()) { - cx.span_bug(item.span, "tuple struct has named fields") + panic!("tuple struct has named fields"); } deserialize_tuple( - cx, - builder, - item.ident, + &item.ident, None, impl_generics, ty, @@ -179,93 +128,97 @@ fn deserialize_body( } Body::Struct(Style::Unit, _) => { deserialize_unit_struct( - cx, - builder, - item.ident, + &item.ident, &item.attrs) } } } // Build `__Visitor(PhantomData, PhantomData, ...)` -fn deserialize_visitor( - builder: &aster::AstBuilder, - generics: &ast::Generics, -) -> (P, P, P) { +// +// Returns: +// +// 1. the struct declaration +// 2. the visitor type, including generics +// 3. the expression for instantiating the visitor +fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) { if generics.lifetimes.is_empty() && generics.ty_params.is_empty() { ( - builder.item().unit_struct("__Visitor"), - builder.ty().id("__Visitor"), - builder.expr().id("__Visitor"), + quote! { + struct __Visitor; + }, + quote!(__Visitor), + quote!(__Visitor), ) } else { - let placeholders : Vec<_> = generics.ty_params.iter() - .map(|t| builder.ty().id(t.ident)) + let num_phantoms = generics.lifetimes.len() + generics.ty_params.len(); + + let phantom_types = generics.lifetimes.iter() + .map(|lifetime_def| { + let lifetime = &lifetime_def.lifetime; + quote!(::std::marker::PhantomData<& #lifetime ()>) + }).chain(generics.ty_params.iter() + .map(|ty_param| { + let ident = &ty_param.ident; + quote!(::std::marker::PhantomData<#ident>) + })); + + let all_params = generics.lifetimes.iter() + .map(|lifetime_def| { + let lifetime = &lifetime_def.lifetime; + quote!(#lifetime) + }).chain(generics.ty_params.iter() + .map(|ty_param| { + let ident = &ty_param.ident; + quote!(#ident) + })); + + let ty_param_idents: Vec<_> = generics.ty_params.iter() + .map(|t| { + let ident = &t.ident; + quote!(#ident) + }) .collect(); + let ty_param_idents = if ty_param_idents.is_empty() { + None + } else { + Some(quote!(::<#(ty_param_idents),*>)) + }; + + let phantom_exprs = (0 .. num_phantoms).map(|_| quote!(::std::marker::PhantomData)); + ( - builder.item().tuple_struct("__Visitor") - .generics().with(generics.clone()).build() - .with_tys({ - let lifetimes = generics.lifetimes.iter() - .map(|lifetime_def| { - builder.ty() - .phantom_data() - .ref_().lifetime(lifetime_def.lifetime.name) - .ty() - .unit() - }); - - let ty_params = generics.ty_params.iter() - .map(|ty_param| { - builder.ty() - .phantom_data() - .id(ty_param.ident) - }); - - lifetimes.chain(ty_params) - }) - .build(), - builder.ty().path() - .segment("__Visitor").with_generics(generics.clone()).build() - .build(), - builder.expr().call() - .path().segment("__Visitor") - .with_tys(placeholders) - .build().build() - .with_args({ - let len = generics.lifetimes.len() + generics.ty_params.len(); - - (0 .. len).map(|_| builder.expr().phantom_data()) - }) - .build(), + quote! { + struct __Visitor #generics ( #(phantom_types),* ); + }, + quote!(__Visitor <#(all_params),*> ), + quote!(__Visitor #ty_param_idents ( #(phantom_exprs),* )), ) } } fn deserialize_unit_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, + type_ident: &syn::Ident, item_attrs: &attr::Item, -) -> P { - let type_name = name_expr(builder, item_attrs.name()); +) -> Tokens { + let type_name = item_attrs.name().deserialize_name(); - quote_block!(cx, { + quote! { struct __Visitor; impl _serde::de::Visitor for __Visitor { - type Value = $type_ident; + type Value = #type_ident; #[inline] - fn visit_unit<__E>(&mut self) -> ::std::result::Result<$type_ident, __E> + fn visit_unit<__E>(&mut self) -> ::std::result::Result<#type_ident, __E> where __E: _serde::de::Error, { - Ok($type_ident) + Ok(#type_ident) } #[inline] - fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$type_ident, __V::Error> + fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<#type_ident, __V::Error> where __V: _serde::de::SeqVisitor, { try!(visitor.end()); @@ -273,39 +226,32 @@ fn deserialize_unit_struct( } } - deserializer.deserialize_unit_struct($type_name, __Visitor) - }).unwrap() + deserializer.deserialize_unit_struct(#type_name, __Visitor) + } } fn deserialize_tuple( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - variant_ident: Option, - impl_generics: &ast::Generics, - ty: P, + type_ident: &syn::Ident, + variant_ident: Option<&syn::Ident>, + impl_generics: &syn::Generics, + ty: syn::Ty, fields: &[Field], item_attrs: &attr::Item, -) -> P { +) -> Tokens { let where_clause = &impl_generics.where_clause; - let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor( - builder, - impl_generics, - ); + let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics); let is_enum = variant_ident.is_some(); let type_path = match variant_ident { - Some(variant_ident) => builder.path().id(type_ident).id(variant_ident).build(), - None => builder.path().id(type_ident).build(), + Some(variant_ident) => quote!(#type_ident::#variant_ident), + None => quote!(#type_ident), }; let nfields = fields.len(); let visit_newtype_struct = if !is_enum && nfields == 1 { Some(deserialize_newtype_struct( - cx, - builder, type_ident, &type_path, impl_generics, @@ -316,90 +262,85 @@ fn deserialize_tuple( }; let visit_seq = deserialize_seq( - cx, - builder, type_ident, - type_path, + &type_path, impl_generics, fields, false, ); let dispatch = if is_enum { - quote_expr!(cx, - visitor.visit_tuple($nfields, $visitor_expr)) + quote!(visitor.visit_tuple(#nfields, #visitor_expr)) } else if nfields == 1 { - let type_name = name_expr(builder, item_attrs.name()); - quote_expr!(cx, - deserializer.deserialize_newtype_struct($type_name, $visitor_expr)) + let type_name = item_attrs.name().deserialize_name(); + quote!(deserializer.deserialize_newtype_struct(#type_name, #visitor_expr)) } else { - let type_name = name_expr(builder, item_attrs.name()); - quote_expr!(cx, - deserializer.deserialize_tuple_struct($type_name, $nfields, $visitor_expr)) + let type_name = item_attrs.name().deserialize_name(); + quote!(deserializer.deserialize_tuple_struct(#type_name, #nfields, #visitor_expr)) }; - quote_block!(cx, { - $visitor_item + quote!({ + #visitor_item - impl $impl_generics _serde::de::Visitor for $visitor_ty $where_clause { - type Value = $ty; + impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { + type Value = #ty; - $visit_newtype_struct + #visit_newtype_struct #[inline] - fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error> + fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<#ty, __V::Error> where __V: _serde::de::SeqVisitor - $visit_seq + { + #visit_seq + } } - $dispatch - }).unwrap() + #dispatch + }) } fn deserialize_seq( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - type_path: ast::Path, - impl_generics: &ast::Generics, + type_ident: &syn::Ident, + type_path: &Tokens, + impl_generics: &syn::Generics, fields: &[Field], is_struct: bool, -) -> P { +) -> Tokens { let mut index_in_seq = 0usize; let let_values: Vec<_> = fields.iter() .enumerate() .map(|(i, field)| { - let name = builder.id(format!("__field{}", i)); + let name = aster::id(format!("__field{}", i)); if field.attrs.skip_deserializing() { - let default = expr_is_missing(cx, builder, &field.attrs); - quote_stmt!(cx, - let $name = $default; - ).unwrap() + let default = expr_is_missing(&field.attrs); + quote! { + let #name = #default; + } } else { let visit = match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; - quote_expr!(cx, try!(visitor.visit::<$field_ty>())) + quote!(try!(visitor.visit::<#field_ty>())) } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - cx, builder, type_ident, impl_generics, &field.ty, path); - quote_expr!(cx, { - $wrapper - $wrapper_impl - try!(visitor.visit::<$wrapper_ty>()).map(|wrap| wrap.value) + type_ident, impl_generics, &field.ty, path); + quote!({ + #wrapper + #wrapper_impl + try!(visitor.visit::<#wrapper_ty>()).map(|wrap| wrap.value) }) } }; - let assign = quote_stmt!(cx, - let $name = match $visit { + let assign = quote! { + let #name = match #visit { Some(value) => { value }, None => { try!(visitor.end()); - return Err(_serde::de::Error::invalid_length($index_in_seq)); + return Err(_serde::de::Error::invalid_length(#index_in_seq)); } }; - ).unwrap(); + }; index_in_seq += 1; assign } @@ -407,110 +348,93 @@ fn deserialize_seq( .collect(); let result = if is_struct { - builder.expr().struct_path(type_path) - .with_id_exprs( - fields.iter() - .enumerate() - .map(|(i, field)| { - ( - match field.ident { - Some(name) => name.clone(), - None => { - cx.span_bug(field.span, "struct contains unnamed fields") - } - }, - builder.expr().id(format!("__field{}", i)), - ) - }) - ) - .build() + let args = fields.iter() + .enumerate() + .map(|(i, field)| { + let ident = field.ident.clone().expect("struct contains unnamed fields"); + let value = aster::id(format!("__field{}", i)); + quote!(#ident: #value) + }); + quote! { + #type_path { #(args),* } + } } else { - builder.expr().call() - .build_path(type_path) - .with_args((0..fields.len()).map(|i| builder.expr().id(format!("__field{}", i)))) - .build() + let args = (0..fields.len()).map(|i| aster::id(format!("__field{}", i))); + quote! { + #type_path ( #(args),* ) + } }; - quote_block!(cx, { - $let_values + quote! { + #(let_values)* try!(visitor.end()); - Ok($result) - }).unwrap() + Ok(#result) + } } fn deserialize_newtype_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - type_path: &ast::Path, - impl_generics: &ast::Generics, + type_ident: &syn::Ident, + type_path: &Tokens, + impl_generics: &syn::Generics, field: &Field, -) -> Vec { +) -> Tokens { let value = match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; - quote_expr!(cx, - try!(<$field_ty as _serde::Deserialize>::deserialize(__e))) + quote! { + try!(<#field_ty as _serde::Deserialize>::deserialize(__e)) + } } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - cx, builder, type_ident, impl_generics, &field.ty, path); - quote_expr!(cx, { - $wrapper - $wrapper_impl - try!(<$wrapper_ty as _serde::Deserialize>::deserialize(__e)).value + type_ident, impl_generics, &field.ty, path); + quote!({ + #wrapper + #wrapper_impl + try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value }) } }; - quote_tokens!(cx, + quote! { #[inline] fn visit_newtype_struct<__E>(&mut self, __e: &mut __E) -> ::std::result::Result where __E: _serde::de::Deserializer, { - Ok($type_path($value)) + Ok(#type_path(#value)) } - ) + } } fn deserialize_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - variant_ident: Option, - impl_generics: &ast::Generics, - ty: P, + type_ident: &syn::Ident, + variant_ident: Option<&syn::Ident>, + impl_generics: &syn::Generics, + ty: syn::Ty, fields: &[Field], item_attrs: &attr::Item, -) -> P { +) -> Tokens { let where_clause = &impl_generics.where_clause; - let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor( - builder, - impl_generics, - ); + let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics); let type_path = match variant_ident { - Some(variant_ident) => builder.path().id(type_ident).id(variant_ident).build(), - None => builder.path().id(type_ident).build(), + Some(ref variant_ident) => quote!(#type_ident::#variant_ident), + None => quote!(#type_ident), }; let visit_seq = deserialize_seq( - cx, - builder, type_ident, - type_path.clone(), + &type_path, impl_generics, fields, true, ); let (field_visitor, fields_stmt, visit_map) = deserialize_struct_visitor( - cx, - builder, type_ident, - type_path.clone(), + type_path, impl_generics, fields, item_attrs, @@ -518,55 +442,57 @@ fn deserialize_struct( let is_enum = variant_ident.is_some(); let dispatch = if is_enum { - quote_expr!(cx, - visitor.visit_struct(FIELDS, $visitor_expr)) + quote! { + visitor.visit_struct(FIELDS, #visitor_expr) + } } else { - let type_name = name_expr(builder, item_attrs.name()); - quote_expr!(cx, - deserializer.deserialize_struct($type_name, FIELDS, $visitor_expr)) + let type_name = item_attrs.name().deserialize_name(); + quote! { + deserializer.deserialize_struct(#type_name, FIELDS, #visitor_expr) + } }; - quote_block!(cx, { - $field_visitor + quote!({ + #field_visitor - $visitor_item + #visitor_item - impl $impl_generics _serde::de::Visitor for $visitor_ty $where_clause { - type Value = $ty; + impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { + type Value = #ty; #[inline] - fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error> + fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<#ty, __V::Error> where __V: _serde::de::SeqVisitor - $visit_seq + { + #visit_seq + } #[inline] - fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error> + fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<#ty, __V::Error> where __V: _serde::de::MapVisitor - $visit_map + { + #visit_map + } } - $fields_stmt + #fields_stmt - $dispatch - }).unwrap() + #dispatch + }) } fn deserialize_item_enum( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - impl_generics: &ast::Generics, - ty: P, + type_ident: &syn::Ident, + impl_generics: &syn::Generics, + ty: syn::Ty, variants: &[Variant], item_attrs: &attr::Item -) -> P { +) -> Tokens { let where_clause = &impl_generics.where_clause; - let type_name = name_expr(builder, item_attrs.name()); + let type_name = item_attrs.name().deserialize_name(); let variant_visitor = deserialize_field_visitor( - cx, - builder, variants.iter() .map(|variant| variant.attrs.name().deserialize_name()) .collect(), @@ -574,32 +500,27 @@ fn deserialize_item_enum( true, ); - let variants_expr = builder.expr().ref_().slice() - .with_exprs( - variants.iter().map(|variant| builder.expr().str(variant.ident)) - ) - .build(); + let variant_names = variants.iter().map(|variant| variant.ident.to_string()); - let variants_stmt = quote_stmt!(cx, - const VARIANTS: &'static [&'static str] = $variants_expr; - ).unwrap(); + let variants_stmt = quote! { + const VARIANTS: &'static [&'static str] = &[ #(variant_names),* ]; + }; let ignored_arm = if item_attrs.deny_unknown_fields() { None } else { - Some(quote_arm!(cx, __Field::__ignore => { Err(_serde::de::Error::end_of_stream()) })) + Some(quote! { + __Field::__ignore => { Err(_serde::de::Error::end_of_stream()) } + }) }; // Match arms to extract a variant from a string let mut variant_arms = vec![]; for (i, variant) in variants.iter().enumerate() { - let variant_name = builder.pat().path() - .id("__Field").id(format!("__field{}", i)) - .build(); + let variant_name = aster::id(format!("__field{}", i)); + let variant_name = quote!(__Field::#variant_name); let block = deserialize_variant( - cx, - builder, type_ident, impl_generics, ty.clone(), @@ -607,71 +528,64 @@ fn deserialize_item_enum( item_attrs, ); - let arm = quote_arm!(cx, $variant_name => $block); + let arm = quote! { + #variant_name => #block + }; variant_arms.push(arm); } variant_arms.extend(ignored_arm.into_iter()); - let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor( - builder, - impl_generics, - ); + let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics); - quote_block!(cx, { - $variant_visitor + quote! { + #variant_visitor - $visitor_item + #visitor_item - impl $impl_generics _serde::de::EnumVisitor for $visitor_ty $where_clause { - type Value = $ty; + impl #impl_generics _serde::de::EnumVisitor for #visitor_ty #where_clause { + type Value = #ty; - fn visit<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error> + fn visit<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<#ty, __V::Error> where __V: _serde::de::VariantVisitor, { match try!(visitor.visit_variant()) { - $variant_arms + #(variant_arms)* } } } - $variants_stmt + #variants_stmt - deserializer.deserialize_enum($type_name, VARIANTS, $visitor_expr) - }).unwrap() + deserializer.deserialize_enum(#type_name, VARIANTS, #visitor_expr) + } } fn deserialize_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - generics: &ast::Generics, - ty: P, + type_ident: &syn::Ident, + generics: &syn::Generics, + ty: syn::Ty, variant: &Variant, item_attrs: &attr::Item, -) -> P { - let variant_ident = variant.ident; +) -> Tokens { + let variant_ident = &variant.ident; match variant.style { Style::Unit => { - quote_block!(cx, { + quote!({ try!(visitor.visit_unit()); - Ok($type_ident::$variant_ident) - }).unwrap() + Ok(#type_ident::#variant_ident) + }) } Style::Newtype => { deserialize_newtype_variant( - cx, - builder, type_ident, - variant_ident, + &variant_ident, generics, &variant.fields[0], ) } Style::Tuple => { deserialize_tuple( - cx, - builder, type_ident, Some(variant_ident), generics, @@ -682,8 +596,6 @@ fn deserialize_variant( } Style::Struct => { deserialize_struct( - cx, - builder, type_ident, Some(variant_ident), generics, @@ -696,146 +608,142 @@ fn deserialize_variant( } fn deserialize_newtype_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - variant_ident: Ident, - impl_generics: &ast::Generics, + type_ident: &syn::Ident, + variant_ident: &syn::Ident, + impl_generics: &syn::Generics, field: &Field, -) -> P { +) -> Tokens { let visit = match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; - quote_expr!(cx, try!(visitor.visit_newtype::<$field_ty>())) + quote!(try!(visitor.visit_newtype::<#field_ty>())) } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - cx, builder, type_ident, impl_generics, &field.ty, path); - quote_expr!(cx, { - $wrapper - $wrapper_impl - try!(visitor.visit_newtype::<$wrapper_ty>()).value + type_ident, impl_generics, &field.ty, path); + quote!({ + #wrapper + #wrapper_impl + try!(visitor.visit_newtype::<#wrapper_ty>()).value }) } }; - quote_block!(cx, { - Ok($type_ident::$variant_ident($visit)) - }).unwrap() + quote! { + Ok(#type_ident::#variant_ident(#visit)), + } } fn deserialize_field_visitor( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - field_names: Vec, + field_names: Vec, item_attrs: &attr::Item, is_variant: bool, -) -> Vec> { +) -> Tokens { // Create the field names for the fields. let field_idents: Vec<_> = (0 .. field_names.len()) - .map(|i| builder.id(format!("__field{}", i))) + .map(|i| aster::id(format!("__field{}", i))) .collect(); let ignore_variant = if item_attrs.deny_unknown_fields() { None } else { - let skip_ident = builder.id("__ignore"); - Some(builder.variant(skip_ident).unit()) + Some(quote!(__ignore,)) }; - let field_enum = builder.item() - .attr().allow(&["non_camel_case_types"]) - .enum_("__Field") - .with_variants( - field_idents.iter().map(|field_ident| { - builder.variant(field_ident).unit() - }) - ) - .with_variants(ignore_variant.into_iter()) - .build(); + let field_enum = quote! { + #[allow(non_camel_case_types)] + enum __Field { + #(field_idents,)* + #ignore_variant + } + }; let index_field_arms: Vec<_> = field_idents.iter() .enumerate() .map(|(field_index, field_ident)| { - quote_arm!(cx, $field_index => { Ok(__Field::$field_ident) }) + quote! { + #field_index => { Ok(__Field::#field_ident) } + } }) .collect(); let (index_error_msg, unknown_ident) = if is_variant { - (builder.expr().str("expected a variant"), builder.id("unknown_variant")) + ("expected a variant", aster::id("unknown_variant")) } else { - (builder.expr().str("expected a field"), builder.id("unknown_field")) + ("expected a field", aster::id("unknown_field")) }; let fallthrough_index_arm_expr = if !is_variant && !item_attrs.deny_unknown_fields() { - quote_expr!(cx, Ok(__Field::__ignore)) + quote! { + Ok(__Field::__ignore) + } } else { - quote_expr!(cx, Err(_serde::de::Error::invalid_value($index_error_msg))) + quote! { + Err(_serde::de::Error::invalid_value(#index_error_msg)) + } }; - let index_body = quote_block!(cx, { + let index_body = quote! { match value { - $index_field_arms - _ => $fallthrough_index_arm_expr + #(index_field_arms)* + _ => #fallthrough_index_arm_expr } - }).unwrap(); - - // Convert the field names into byte strings. - let str_field_names: Vec<_> = field_names.iter() - .map(|name| builder.expr().lit().str(&name)) - .collect(); + }; // Match arms to extract a field from a string - let str_field_arms: Vec<_> = field_idents.iter().zip(str_field_names.iter()) + let str_field_arms: Vec<_> = field_idents.iter().zip(field_names.iter()) .map(|(field_ident, field_name)| { - quote_arm!(cx, $field_name => { Ok(__Field::$field_ident) }) + quote! { + #field_name => { Ok(__Field::#field_ident) } + } }) .collect(); let fallthrough_str_arm_expr = if !is_variant && !item_attrs.deny_unknown_fields() { - quote_expr!(cx, Ok(__Field::__ignore)) + quote! { + Ok(__Field::__ignore) + } } else { - quote_expr!(cx, Err(_serde::de::Error::$unknown_ident(value))) + quote! { + Err(_serde::de::Error::#unknown_ident(value)) + } }; - let str_body = quote_block!(cx, { + let str_body = quote! { match value { - $str_field_arms - _ => $fallthrough_str_arm_expr + #(str_field_arms)* + _ => #fallthrough_str_arm_expr } - }).unwrap(); - - // Convert the field names into byte strings. - let bytes_field_names: Vec<_> = field_names.iter() - .map(|name| { - let name: &str = name; - builder.expr().lit().byte_str(name) - }) - .collect(); + }; // Match arms to extract a field from a string - let bytes_field_arms: Vec<_> = field_idents.iter().zip(bytes_field_names.iter()) + let bytes_field_arms: Vec<_> = field_idents.iter().zip(field_names.iter()) .map(|(field_ident, field_name)| { - quote_arm!(cx, $field_name => { Ok(__Field::$field_ident) }) + let bytes_field_name = quote::ByteStr(&field_name); + quote! { + #bytes_field_name => { Ok(__Field::#field_ident) } + } }) .collect(); let fallthrough_bytes_arm_expr = if !is_variant && !item_attrs.deny_unknown_fields() { - quote_expr!(cx, Ok(__Field::__ignore)) + quote! { + Ok(__Field::__ignore) + } } else { - quote_expr!(cx, { + quote!({ let value = ::std::string::String::from_utf8_lossy(value); - Err(_serde::de::Error::$unknown_ident(&value)) + Err(_serde::de::Error::#unknown_ident(&value)) }) }; - let bytes_body = quote_block!(cx, { + let bytes_body = quote! { match value { - $bytes_field_arms - _ => $fallthrough_bytes_arm_expr + #(bytes_field_arms)* + _ => #fallthrough_bytes_arm_expr } - }).unwrap(); + }; - let impl_item = quote_item!(cx, + let impl_item = quote! { impl _serde::de::Deserialize for __Field { #[inline] fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<__Field, __D::Error> @@ -848,49 +756,52 @@ fn deserialize_field_visitor( fn visit_usize<__E>(&mut self, value: usize) -> ::std::result::Result<__Field, __E> where __E: _serde::de::Error - $index_body + { + #index_body + } fn visit_str<__E>(&mut self, value: &str) -> ::std::result::Result<__Field, __E> where __E: _serde::de::Error - $str_body + { + #str_body + } fn visit_bytes<__E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, __E> where __E: _serde::de::Error - $bytes_body + { + #bytes_body + } } deserializer.deserialize_struct_field(__FieldVisitor) } } - ).unwrap(); + }; - vec![field_enum, impl_item] + quote! { + #field_enum + #impl_item + } } fn deserialize_struct_visitor( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - struct_path: ast::Path, - impl_generics: &ast::Generics, + type_ident: &syn::Ident, + struct_path: Tokens, + impl_generics: &syn::Generics, fields: &[Field], item_attrs: &attr::Item, -) -> (Vec>, ast::Stmt, P) { +) -> (Tokens, Tokens, Tokens) { let field_exprs = fields.iter() .map(|field| field.attrs.name().deserialize_name()) .collect(); let field_visitor = deserialize_field_visitor( - cx, - builder, field_exprs, item_attrs, false, ); let visit_map = deserialize_map( - cx, - builder, type_ident, struct_path, impl_generics, @@ -898,82 +809,73 @@ fn deserialize_struct_visitor( item_attrs, ); - let fields_expr = builder.expr().ref_().slice() - .with_exprs( - fields.iter() - .map(|field| { - match field.ident { - Some(name) => builder.expr().str(name), - None => { - cx.span_bug(field.span, "struct contains unnamed fields") - } - } - }) - ) - .build(); + let field_names = fields.iter().map(|field| { + field.ident.clone().expect("struct contains unnamed field").to_string() + }); - let fields_stmt = quote_stmt!(cx, - const FIELDS: &'static [&'static str] = $fields_expr; - ).unwrap(); + let fields_stmt = quote! { + const FIELDS: &'static [&'static str] = &[ #(field_names),* ]; + }; (field_visitor, fields_stmt, visit_map) } fn deserialize_map( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - struct_path: ast::Path, - impl_generics: &ast::Generics, + type_ident: &syn::Ident, + struct_path: Tokens, + impl_generics: &syn::Generics, fields: &[Field], item_attrs: &attr::Item, -) -> P { +) -> Tokens { // Create the field names for the fields. let fields_names = fields.iter() .enumerate() .map(|(i, field)| - (field, builder.id(format!("__field{}", i)))) + (field, aster::id(format!("__field{}", i)))) .collect::>(); // Declare each field that will be deserialized. - let let_values: Vec = fields_names.iter() + let let_values: Vec<_> = fields_names.iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) - .map(|&(field, name)| { + .map(|&(field, ref name)| { let field_ty = &field.ty; - quote_stmt!(cx, let mut $name: Option<$field_ty> = None;).unwrap() + quote! { + let mut #name: Option<#field_ty> = None; + } }) .collect(); // Match arms to extract a value for a field. let value_arms = fields_names.iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) - .map(|&(ref field, name)| { + .map(|&(ref field, ref name)| { let deser_name = field.attrs.name().deserialize_name(); - let name_str = builder.expr().lit().str(deser_name); let visit = match field.attrs.deserialize_with() { None => { let field_ty = &field.ty; - quote_expr!(cx, try!(visitor.visit_value::<$field_ty>())) + quote! { + try!(visitor.visit_value::<#field_ty>()) + } } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - cx, builder, type_ident, impl_generics, &field.ty, path); - quote_expr!(cx, ({ - $wrapper - $wrapper_impl - try!(visitor.visit_value::<$wrapper_ty>()).value - })) + type_ident, impl_generics, &field.ty, path); + quote!({ + #wrapper + #wrapper_impl + try!(visitor.visit_value::<#wrapper_ty>()).value + }) } }; - quote_arm!(cx, - __Field::$name => { - if $name.is_some() { - return Err(<__V::Error as _serde::de::Error>::duplicate_field($name_str)); + quote! { + __Field::#name => { + if #name.is_some() { + return Err(<__V::Error as _serde::de::Error>::duplicate_field(#deser_name)); } - $name = Some($visit); + #name = Some(#visit); } - ) + } }) .collect::>(); @@ -981,12 +883,12 @@ fn deserialize_map( // Ignored even if `deny_unknown_fields` is set. let skipped_arms = fields_names.iter() .filter(|&&(field, _)| field.attrs.skip_deserializing()) - .map(|&(_, name)| { - quote_arm!(cx, - __Field::$name => { + .map(|&(_, ref name)| { + quote! { + __Field::#name => { try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); } - ) + } }) .collect::>(); @@ -994,78 +896,66 @@ fn deserialize_map( let ignored_arm = if item_attrs.deny_unknown_fields() { None } else { - Some(quote_arm!(cx, + Some(quote! { _ => { try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); } - )) + }) }; let extract_values = fields_names.iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) - .map(|&(field, name)| { - let missing_expr = expr_is_missing(cx, builder, &field.attrs); + .map(|&(field, ref name)| { + let missing_expr = expr_is_missing(&field.attrs); - quote_stmt!(cx, - let $name = match $name { - Some($name) => $name, - None => $missing_expr + quote! { + let #name = match #name { + Some(#name) => #name, + None => #missing_expr }; - ).unwrap() + } }) .collect::>(); - let result = builder.expr().struct_path(struct_path) - .with_id_exprs( - fields_names.iter() - .map(|&(field, name)| { - ( - match field.ident { - Some(name) => name.clone(), - None => { - cx.span_bug(field.span, "struct contains unnamed fields") - } - }, - if field.attrs.skip_deserializing() { - expr_is_missing(cx, builder, &field.attrs) - } else { - builder.expr().id(name) - } - ) - }) - ) - .build(); + let result = fields_names.iter() + .map(|&(field, ref name)| { + let ident = field.ident.clone().expect("struct contains unnamed fields"); + let value = if field.attrs.skip_deserializing() { + expr_is_missing(&field.attrs) + } else { + quote!(#name) + }; + quote!(#ident: #value) + }); - quote_block!(cx, { - $let_values + quote! { + #(let_values)* while let Some(key) = try!(visitor.visit_key::<__Field>()) { match key { - $value_arms - $skipped_arms - $ignored_arm + #(value_arms)* + #(skipped_arms)* + #ignored_arm } } try!(visitor.end()); - $extract_values + #(extract_values)* - Ok($result) - }).unwrap() + Ok(#struct_path { #(result),* }) + } } /// This function wraps the expression in `#[serde(deserialize_with="...")]` in /// a trait to prevent it from accessing the internal `Deserialize` state. fn wrap_deserialize_with( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - impl_generics: &ast::Generics, - field_ty: &P, - deserialize_with: &ast::Path, -) -> (ast::Stmt, ast::Stmt, ast::Path) { + type_ident: &syn::Ident, + impl_generics: &syn::Generics, + field_ty: &syn::Ty, + deserialize_with: &syn::Path, +) -> (Tokens, Tokens, syn::Path) { // Quasi-quoting doesn't do a great job of expanding generics into paths, // so manually build it. - let wrapper_ty = builder.path() + let wrapper_ty = aster::path() .segment("__SerdeDeserializeWithStruct") .with_generics(impl_generics.clone()) .build() @@ -1073,97 +963,82 @@ fn wrap_deserialize_with( let where_clause = &impl_generics.where_clause; - let phantom_ty = builder.path() + let phantom_ty = aster::path() .segment(type_ident) - .with_generics(builder.from_generics(impl_generics.clone()) + .with_generics(aster::from_generics(impl_generics.clone()) .strip_ty_params() .build()) .build() .build(); ( - quote_stmt!(cx, - struct __SerdeDeserializeWithStruct $impl_generics $where_clause { - value: $field_ty, - phantom: ::std::marker::PhantomData<$phantom_ty>, + quote! { + struct __SerdeDeserializeWithStruct #impl_generics #where_clause { + value: #field_ty, + phantom: ::std::marker::PhantomData<#phantom_ty>, } - ).unwrap(), - quote_stmt!(cx, - impl $impl_generics _serde::de::Deserialize for $wrapper_ty $where_clause { + }, + quote! { + impl #impl_generics _serde::de::Deserialize for #wrapper_ty #where_clause { fn deserialize<__D>(__d: &mut __D) -> ::std::result::Result where __D: _serde::de::Deserializer { - let value = try!($deserialize_with(__d)); + let value = try!(#deserialize_with(__d)); Ok(__SerdeDeserializeWithStruct { value: value, phantom: ::std::marker::PhantomData, }) } } - ).unwrap(), + }, wrapper_ty, ) } -fn expr_is_missing( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - attrs: &attr::Field, -) -> P { +fn expr_is_missing(attrs: &attr::Field) -> Tokens { match *attrs.default() { attr::FieldDefault::Default => { - return quote_expr!(cx, ::std::default::Default::default()); + return quote!(::std::default::Default::default()); } attr::FieldDefault::Path(ref path) => { - return quote_expr!(cx, $path()); + return quote!(#path()); } attr::FieldDefault::None => { /* below */ } } - let name = name_expr(builder, attrs.name()); + let name = attrs.name().deserialize_name(); match attrs.deserialize_with() { None => { - quote_expr!(cx, try!(visitor.missing_field($name))) + quote! { + try!(visitor.missing_field(#name)) + } } Some(_) => { - quote_expr!(cx, return Err( - <__V::Error as _serde::de::Error>::missing_field($name))) + quote! { + return Err(<__V::Error as _serde::de::Error>::missing_field(#name)) + } } } } -fn name_expr( - builder: &aster::AstBuilder, - name: &attr::Name, -) -> P { - builder.expr().str(name.deserialize_name()) -} - -fn check_no_str( - cx: &ExtCtxt, - item: &Item, -) -> Result<(), ()> { - let fail = |field: &Field| { - cx.span_err( - field.span, +fn check_no_str(cx: &internals::Ctxt, item: &Item) { + let fail = || { + cx.error( "Serde does not support deserializing fields of type &str; \ consider using String instead"); - Err(()) }; for field in item.body.all_fields() { if field.attrs.skip_deserializing() || field.attrs.deserialize_with().is_some() { continue } - if let ast::TyKind::Rptr(_, ref inner) = field.ty.node { - if let ast::TyKind::Path(_, ref path) = inner.ty.node { - if path.segments.len() == 1 - && path.segments[0].identifier.name.as_str() == "str" - { - return fail(field); + if let syn::Ty::Rptr(_, ref inner) = *field.ty { + if let syn::Ty::Path(_, ref path) = inner.ty { + if path.segments.len() == 1 && path.segments[0].ident == "str" { + fail(); + return; } } } } - Ok(()) } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 7de4db6d..d3f0cab1 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -1,3 +1,5 @@ +#![recursion_limit = "1000"] + #![cfg_attr(feature = "clippy", plugin(clippy))] #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", allow(too_many_arguments))] @@ -31,6 +33,7 @@ use std::path::Path; use syntax::feature_gate::AttributeType; mod bound; +mod de; mod ser; #[cfg(feature = "with-syntex")] @@ -67,7 +70,7 @@ fn syntex_registry() -> syntex::Registry { reg.add_attr("feature(custom_attribute)"); reg.add_decorator("derive_Serialize", expand_derive_serialize); - reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize); + reg.add_decorator("derive_Deserialize", expand_derive_deserialize); reg.add_post_expansion_pass(strip_attributes); @@ -107,53 +110,56 @@ pub fn register(reg: &mut rustc_plugin::Registry) { syntax::ext::base::MultiDecorator( Box::new(expand_derive_serialize))); - /*reg.register_syntax_extension( + reg.register_syntax_extension( syntax::parse::token::intern("derive_Deserialize"), syntax::ext::base::MultiDecorator( - Box::new(de::expand_derive_deserialize)));*/ + Box::new(expand_derive_deserialize))); reg.register_attribute("serde".to_owned(), AttributeType::Normal); } -#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] -use syntax::ast::MetaItem; -#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] -use syntax::codemap::Span; -#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] -use syntax::ext::base::{Annotatable, ExtCtxt}; +macro_rules! shim { + ($name:ident $pkg:ident :: $func:ident) => { + fn $func( + cx: &mut ::syntax::ext::base::ExtCtxt, + _span: ::syntax::codemap::Span, + meta_item: &::syntax::ast::MetaItem, + annotatable: &::syntax::ext::base::Annotatable, + push: &mut FnMut(::syntax::ext::base::Annotatable) + ) { + let item = match *annotatable { + ::syntax::ext::base::Annotatable::Item(ref item) => item, + _ => { + cx.span_err( + meta_item.span, + concat!("`#[derive(", + stringify!($name), + ")]` may only be applied to structs and enums")); + return; + } + }; -#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] -fn expand_derive_serialize( - cx: &mut ExtCtxt, - _span: Span, - meta_item: &MetaItem, - annotatable: &Annotatable, - push: &mut FnMut(Annotatable) -) { - let item = match *annotatable { - Annotatable::Item(ref item) => item, - _ => { - cx.span_err( - meta_item.span, - "`#[derive(Serialize)]` may only be applied to structs and enums"); - return; + use syntax::print::pprust; + let s = pprust::item_to_string(item); + + let syn_item = syn::parse_item(&s).unwrap(); + let expanded = $pkg::$func(&syn_item).to_string(); + + use syntax::parse; + let name = stringify!($name).to_string(); + let cfg = Vec::new(); + let sess = parse::ParseSess::new(); + let impl_item = parse::parse_item_from_source_str(name, expanded, cfg, &sess); + push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap())); } }; - - use syntax::print::pprust; - let s = pprust::item_to_string(item); - - let syn_item = syn::parse_item(&s).unwrap(); - let expanded = ser::expand_derive_serialize(&syn_item).to_string(); - - use syntax::parse; - let name = "Serialize".to_string(); - let cfg = Vec::new(); - let sess = parse::ParseSess::new(); - let impl_item = parse::parse_item_from_source_str(name, expanded, cfg, &sess); - push(Annotatable::Item(impl_item.unwrap().unwrap())); } +#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] +shim!(Serialize ser::expand_derive_serialize); +#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] +shim!(Deserialize de::expand_derive_deserialize); + #[cfg(feature = "with-syn")] pub fn expand_single_item(item: &str) -> String { let syn_item = syn::parse_item(item).unwrap(); @@ -164,7 +170,7 @@ pub fn expand_single_item(item: &str) -> String { None }; let expanded_de = if de { - unimplemented!() + Some(de::expand_derive_deserialize(&syn_item)) } else { None:: }; From a69b82c7c594569a8c0eba30b3749aed905b415a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 12 Sep 2016 01:26:47 -0700 Subject: [PATCH 028/111] Recursion limit --- serde_codegen/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index d3f0cab1..8dbfdf31 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -1,11 +1,12 @@ -#![recursion_limit = "1000"] - #![cfg_attr(feature = "clippy", plugin(clippy))] #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", allow(too_many_arguments))] #![cfg_attr(feature = "clippy", allow(used_underscore_binding))] #![cfg_attr(feature = "with-libsyntax", feature(rustc_private, plugin))] +// The `quote!` macro requires deep recursion. +#![recursion_limit = "192"] + extern crate serde_codegen_internals as internals; #[cfg(feature = "with-syntex")] From 429de89276f056b132cda2115e5f122c035e0a88 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 21 Sep 2016 15:06:21 +0200 Subject: [PATCH 029/111] Release 0.8.9 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 18 +++++++++--------- serde_codegen_internals/Cargo.toml | 6 +++--- serde_derive/Cargo.toml | 8 ++++---- serde_macros/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 93c11cbe..29765444 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.8" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 703575e7..bc18fa03 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.8" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -25,14 +25,14 @@ with-syntex = [ ] [build-dependencies] -quasi_codegen = { version = "^0.19.0", optional = true } -syntex = { version = "^0.43.0", optional = true } +quasi_codegen = { version = "^0.20.0", optional = true } +syntex = { version = "^0.44.0", optional = true } [dependencies] -aster = { version = "^0.26.0", default-features = false } +aster = { version = "^0.27.0", default-features = false } clippy = { version = "^0.*", optional = true } -quasi = { version = "^0.19.0", default-features = false } -quasi_macros = { version = "^0.19.0", optional = true } -serde_codegen_internals = { version = "=0.8.0", default-features = false, path = "../serde_codegen_internals" } -syntex = { version = "^0.43.0", optional = true } -syntex_syntax = { version = "^0.43.0", optional = true } +quasi = { version = "^0.20.0", default-features = false } +quasi_macros = { version = "^0.20.0", optional = true } +serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } +syntex = { version = "^0.44.0", optional = true } +syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 3219579d..cd848f47 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.8.0" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." @@ -17,5 +17,5 @@ with-syntex = ["syntex_syntax", "syntex_errors"] [dependencies] clippy = { version = "^0.*", optional = true } -syntex_syntax = { version = "^0.43.0", optional = true } -syntex_errors = { version = "^0.43.0", optional = true } +syntex_syntax = { version = "^0.44.0", optional = true } +syntex_errors = { version = "^0.44.0", optional = true } diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 66930b14..9c923194 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.8" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,9 +15,9 @@ name = "serde_derive" rustc-macro = true [dependencies] -serde_codegen = { version = "=0.8.8", path = "../serde_codegen" } +serde_codegen = { version = "=0.8.9", path = "../serde_codegen" } [dev-dependencies] fnv = "1.0" -serde = { version = "0.8.8", path = "../serde" } -serde_test = { version = "0.8.8", path = "../serde_test" } +serde = { version = "0.8.9", path = "../serde" } +serde_test = { version = "0.8.9", path = "../serde_test" } diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml index ba892a66..62b5e682 100644 --- a/serde_macros/Cargo.toml +++ b/serde_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_macros" -version = "0.8.8" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,14 +23,14 @@ unstable-testing = [ [dependencies] clippy = { version = "^0.*", optional = true } -serde_codegen = { version = "=0.8.8", default-features = false, features = ["unstable"], path = "../serde_codegen" } +serde_codegen = { version = "=0.8.9", default-features = false, features = ["unstable"], path = "../serde_codegen" } [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" rustc-serialize = "^0.3.16" -serde = { version = "0.8.8", path = "../serde" } -serde_test = { version = "0.8.8", path = "../serde_test" } +serde = { version = "0.8.9", path = "../serde" } +serde_test = { version = "0.8.9", path = "../serde_test" } [[test]] name = "test" diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index c9d6e9b5..a0d9ab65 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.8" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.8", path = "../serde" } +serde = { version = "0.8.9", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index bac9bfa9..03a8ab4a 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.8" +version = "0.8.9" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 1eca7766ba67ed9234d099fbd53f12bf19222deb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Sep 2016 09:54:10 -0700 Subject: [PATCH 030/111] Bump syn dependency --- serde_codegen/Cargo.toml | 2 +- serde_codegen/src/de.rs | 2 +- serde_codegen/src/lib.rs | 13 ++++---- serde_codegen/src/ser.rs | 2 +- serde_codegen_internals/Cargo.toml | 2 +- serde_codegen_internals/src/ast.rs | 2 +- serde_codegen_internals/src/attr.rs | 47 ++++++++++++++++++++--------- 7 files changed, 44 insertions(+), 26 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 9b469f1c..132547be 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -25,6 +25,6 @@ with-syn = [] clippy = { version = "^0.*", optional = true } quote = "0.1" serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } -syn = { version = "0.5", features = ["aster", "visit"] } +syn = { version = "0.7", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index dae4ca65..d8a147d0 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -5,7 +5,7 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_deserialize(item: &syn::Item) -> Tokens { +pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Tokens { let item = { let ctxt = internals::Ctxt::new(); let item = Item::from_ast(&ctxt, item); diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 8dbfdf31..fed63700 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -143,7 +143,7 @@ macro_rules! shim { use syntax::print::pprust; let s = pprust::item_to_string(item); - let syn_item = syn::parse_item(&s).unwrap(); + let syn_item = syn::parse_macro_input(&s).unwrap(); let expanded = $pkg::$func(&syn_item).to_string(); use syntax::parse; @@ -163,7 +163,7 @@ shim!(Deserialize de::expand_derive_deserialize); #[cfg(feature = "with-syn")] pub fn expand_single_item(item: &str) -> String { - let syn_item = syn::parse_item(item).unwrap(); + let syn_item = syn::parse_macro_input(item).unwrap(); let (ser, de, syn_item) = strip_serde_derives(syn_item); let expanded_ser = if ser { Some(ser::expand_derive_serialize(&syn_item)) @@ -178,10 +178,10 @@ pub fn expand_single_item(item: &str) -> String { let syn_item = strip_serde_attrs(syn_item); return quote!(#expanded_ser #expanded_de #syn_item).to_string(); - fn strip_serde_derives(item: syn::Item) -> (bool, bool, syn::Item) { + fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) { let mut ser = false; let mut de = false; - let item = syn::Item { + let item = syn::MacroInput { attrs: item.attrs.into_iter().flat_map(|attr| { if attr.is_sugared_doc { return Some(attr); @@ -223,8 +223,8 @@ pub fn expand_single_item(item: &str) -> String { (ser, de, item) } - fn strip_serde_attrs(item: syn::Item) -> syn::Item { - syn::Item { + fn strip_serde_attrs(item: syn::MacroInput) -> syn::MacroInput { + syn::MacroInput { attrs: strip_serde_from_attrs(item.attrs), body: match item.body { syn::Body::Enum(variants) => syn::Body::Enum( @@ -233,6 +233,7 @@ pub fn expand_single_item(item: &str) -> String { ident: variant.ident, attrs: strip_serde_from_attrs(variant.attrs), data: strip_serde_from_variant_data(variant.data), + discriminant: variant.discriminant, } }).collect() ), diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 448c974c..3500a230 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -5,7 +5,7 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_serialize(item: &syn::Item) -> Tokens { +pub fn expand_derive_serialize(item: &syn::MacroInput) -> Tokens { let item = Item::from_ast(&internals::Ctxt::new(), item); let impl_generics = build_impl_generics(&item); diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index a364739b..f501786f 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -15,4 +15,4 @@ unstable-testing = ["clippy"] [dependencies] clippy = { version = "^0.*", optional = true } -syn = "0.5" +syn = "0.7" diff --git a/serde_codegen_internals/src/ast.rs b/serde_codegen_internals/src/ast.rs index d62ad807..2941c164 100644 --- a/serde_codegen_internals/src/ast.rs +++ b/serde_codegen_internals/src/ast.rs @@ -35,7 +35,7 @@ pub enum Style { } impl<'a> Item<'a> { - pub fn from_ast(cx: &Ctxt, item: &'a syn::Item) -> Item<'a> { + pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> { let attrs = attr::Item::from_ast(cx, item); let body = match item.body { diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 02b72b6c..44da33e3 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -94,7 +94,7 @@ pub struct Item { impl Item { /// Extract out the `#[serde(...)]` attributes from an item. - pub fn from_ast(cx: &Ctxt, item: &syn::Item) -> Self { + pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields"); @@ -106,8 +106,10 @@ impl Item { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - ser_name.set(lit.clone()); - de_name.set(lit.clone()); + if let Ok(s) = get_string_from_lit(cx, name, lit) { + ser_name.set(s.clone()); + de_name.set(s); + } } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` @@ -191,8 +193,10 @@ impl Variant { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - ser_name.set(lit.clone()); - de_name.set(lit.clone()); + if let Ok(s) = get_string_from_lit(cx, name, lit) { + ser_name.set(s.clone()); + de_name.set(s); + } } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` @@ -275,8 +279,10 @@ impl Field { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - ser_name.set(lit.clone()); - de_name.set(lit.clone()); + if let Ok(s) = get_string_from_lit(cx, name, lit) { + ser_name.set(s.clone()); + de_name.set(s); + } } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` @@ -421,7 +427,7 @@ fn get_ser_and_de( items: &[syn::MetaItem], f: F ) -> Result, ()> - where F: Fn(&Ctxt, &Ident, &str) -> Result, + where F: Fn(&Ctxt, &Ident, &syn::Lit) -> Result, { let mut ser_item = Attr::none(cx, attribute); let mut de_item = Attr::none(cx, attribute); @@ -454,7 +460,7 @@ fn get_renames( cx: &Ctxt, items: &[syn::MetaItem], ) -> Result, ()> { - get_ser_and_de(cx, "rename", items, |_, _, s| Ok(s.to_owned())) + get_ser_and_de(cx, "rename", items, get_string_from_lit) } fn get_where_predicates( @@ -473,17 +479,28 @@ pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> } } -fn parse_lit_into_path(cx: &Ctxt, name: &Ident, lit: &str) -> Result { - // TODO handle error - Ok(syn::parse_path(lit).unwrap()) +fn get_string_from_lit(_cx: &Ctxt, _name: &Ident, lit: &syn::Lit) -> Result { + if let syn::Lit::Str(ref s, _) = *lit { + Ok(s.clone()) + } else { + // TODO handle error + Err(()) + } } -fn parse_lit_into_where(cx: &Ctxt, name: &Ident, lit: &str) -> Result, ()> { - if lit.is_empty() { +fn parse_lit_into_path(cx: &Ctxt, name: &Ident, lit: &syn::Lit) -> Result { + let string = try!(get_string_from_lit(cx, name, lit)); + // TODO handle error + Ok(syn::parse_path(&string).unwrap()) +} + +fn parse_lit_into_where(cx: &Ctxt, name: &Ident, lit: &syn::Lit) -> Result, ()> { + let string = try!(get_string_from_lit(cx, name, lit)); + if string.is_empty() { return Ok(Vec::new()); } - let where_string = format!("where {}", lit); + let where_string = format!("where {}", string); // TODO handle error Ok(syn::parse_where_clause(&where_string).unwrap().predicates) From f47a50e996af699ad4e3c87a084573f819e23ca8 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 26 Sep 2016 21:09:13 -0700 Subject: [PATCH 031/111] Make serde state variable unique by naming it __serde_state Closes #557 --- serde_codegen/src/ser.rs | 28 ++++++++++++++++------------ testing/tests/test_macros.rs | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index d4883e8e..7023c9b6 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -230,9 +230,9 @@ fn serialize_tuple_struct( let let_mut = mut_if(cx, len > 0); quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); + let $let_mut __serde_state = try!(_serializer.serialize_tuple_struct($type_name, $len)); $serialize_stmts - _serializer.serialize_tuple_struct_end(state) + _serializer.serialize_tuple_struct_end(__serde_state) }).unwrap() } @@ -275,9 +275,9 @@ fn serialize_struct( .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_struct($type_name, $len)); + let $let_mut __serde_state = try!(_serializer.serialize_struct($type_name, $len)); $serialize_fields - _serializer.serialize_struct_end(state) + _serializer.serialize_struct_end(__serde_state) }).unwrap() } @@ -469,9 +469,13 @@ fn serialize_tuple_variant( let let_mut = mut_if(cx, len > 0); quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); + let $let_mut __serde_state = try!(_serializer.serialize_tuple_variant( + $type_name, + $variant_index, + $variant_name, + $len)); $serialize_stmts - _serializer.serialize_tuple_variant_end(state) + _serializer.serialize_tuple_variant_end(__serde_state) }).unwrap() } @@ -517,14 +521,14 @@ fn serialize_struct_variant( .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_struct_variant( + let $let_mut __serde_state = try!(_serializer.serialize_struct_variant( $item_name, $variant_index, $variant_name, $len, )); $serialize_fields - _serializer.serialize_struct_variant_end(state) + _serializer.serialize_struct_variant_end(__serde_state) }).unwrap() } @@ -555,7 +559,7 @@ fn serialize_tuple_struct_visitor( } let ser = quote_expr!(cx, - try!(_serializer.$func(&mut state, $field_expr)); + try!(_serializer.$func(&mut __serde_state, $field_expr)); ); match skip { @@ -596,7 +600,7 @@ fn serialize_struct_visitor( } let ser = quote_expr!(cx, - try!(_serializer.$func(&mut state, $key_expr, $field_expr)); + try!(_serializer.$func(&mut __serde_state, $key_expr, $field_expr)); ); match skip { @@ -659,8 +663,8 @@ fn name_expr( // Serialization of an empty struct results in code like: // -// let mut state = try!(serializer.serialize_struct("S", 0)); -// serializer.serialize_struct_end(state) +// let mut __serde_state = try!(serializer.serialize_struct("S", 0)); +// serializer.serialize_struct_end(__serde_state) // // where we want to omit the `mut` to avoid a warning. fn mut_if(cx: &ExtCtxt, is_mut: bool) -> Vec { diff --git a/testing/tests/test_macros.rs b/testing/tests/test_macros.rs index a6b1d167..6e5e1d82 100644 --- a/testing/tests/test_macros.rs +++ b/testing/tests/test_macros.rs @@ -600,3 +600,28 @@ fn test_default_ty_param() { ] ); } + +#[test] +fn test_enum_state_field() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum SomeEnum { + Key { key: char, state: bool }, + } + + assert_tokens( + &SomeEnum::Key { key: 'a', state: true }, + &[ + Token::EnumMapStart("SomeEnum", "Key", 2), + + Token::EnumMapSep, + Token::Str("key"), + Token::Char('a'), + + Token::EnumMapSep, + Token::Str("state"), + Token::Bool(true), + + Token::EnumMapEnd, + ] + ); +} From 20afa850876ba2495192696ac0dbe5021f65eaf4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 26 Sep 2016 22:08:21 -0700 Subject: [PATCH 032/111] Bump quasi and aster --- serde_codegen/Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index bc18fa03..033ebd8e 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -25,14 +25,14 @@ with-syntex = [ ] [build-dependencies] -quasi_codegen = { version = "^0.20.0", optional = true } +quasi_codegen = { version = "^0.21.0", optional = true } syntex = { version = "^0.44.0", optional = true } [dependencies] -aster = { version = "^0.27.0", default-features = false } +aster = { version = "^0.29.0", default-features = false } clippy = { version = "^0.*", optional = true } -quasi = { version = "^0.20.0", default-features = false } -quasi_macros = { version = "^0.20.0", optional = true } +quasi = { version = "^0.21.0", default-features = false } +quasi_macros = { version = "^0.21.0", optional = true } serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } From 8e865f62c4bfaa01c7b94c89487e8d06814d984f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 26 Sep 2016 22:13:53 -0700 Subject: [PATCH 033/111] Fix conflicts with the __serde_state commit --- serde_codegen/src/ser.rs | 120 +++++---------------------------------- 1 file changed, 14 insertions(+), 106 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 7aad69a2..de27e912 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -164,25 +164,11 @@ fn serialize_tuple_struct( let len = serialize_stmts.len(); let let_mut = mut_if(len > 0); -<<<<<<< HEAD quote! { - let #let_mut state = try!(_serializer.serialize_tuple_struct(#type_name, #len)); + let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len)); #(serialize_stmts)* - _serializer.serialize_tuple_struct_end(state) - } -||||||| merged common ancestors - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); - $serialize_stmts - _serializer.serialize_tuple_struct_end(state) - }).unwrap() -======= - quote_block!(cx, { - let $let_mut __serde_state = try!(_serializer.serialize_tuple_struct($type_name, $len)); - $serialize_stmts _serializer.serialize_tuple_struct_end(__serde_state) - }).unwrap() ->>>>>>> origin/master + } } fn serialize_struct( @@ -219,25 +205,11 @@ fn serialize_struct( }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); -<<<<<<< HEAD quote! { - let #let_mut state = try!(_serializer.serialize_struct(#type_name, #len)); + let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len)); #(serialize_fields)* - _serializer.serialize_struct_end(state) - } -||||||| merged common ancestors - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_struct($type_name, $len)); - $serialize_fields - _serializer.serialize_struct_end(state) - }).unwrap() -======= - quote_block!(cx, { - let $let_mut __serde_state = try!(_serializer.serialize_struct($type_name, $len)); - $serialize_fields _serializer.serialize_struct_end(__serde_state) - }).unwrap() ->>>>>>> origin/master + } } fn serialize_item_enum( @@ -401,29 +373,15 @@ fn serialize_tuple_variant( let len = serialize_stmts.len(); let let_mut = mut_if(len > 0); -<<<<<<< HEAD quote! { - let #let_mut state = try!(_serializer.serialize_tuple_variant(#type_name, #variant_index, #variant_name, #len)); + let #let_mut __serde_state = try!(_serializer.serialize_tuple_variant( + #type_name, + #variant_index, + #variant_name, + #len)); #(serialize_stmts)* - _serializer.serialize_tuple_variant_end(state) - } -||||||| merged common ancestors - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); - $serialize_stmts - _serializer.serialize_tuple_variant_end(state) - }).unwrap() -======= - quote_block!(cx, { - let $let_mut __serde_state = try!(_serializer.serialize_tuple_variant( - $type_name, - $variant_index, - $variant_name, - $len)); - $serialize_stmts _serializer.serialize_tuple_variant_end(__serde_state) - }).unwrap() ->>>>>>> origin/master + } } fn serialize_struct_variant( @@ -459,48 +417,18 @@ fn serialize_struct_variant( None => quote!(1), } }) -<<<<<<< HEAD .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); quote! { - let #let_mut state = try!(_serializer.serialize_struct_variant( + let #let_mut __serde_state = try!(_serializer.serialize_struct_variant( #item_name, #variant_index, #variant_name, #len, -||||||| merged common ancestors - .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); - - quote_block!(cx, { - let $let_mut state = try!(_serializer.serialize_struct_variant( - $item_name, - $variant_index, - $variant_name, - $len, -======= - .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); - - quote_block!(cx, { - let $let_mut __serde_state = try!(_serializer.serialize_struct_variant( - $item_name, - $variant_index, - $variant_name, - $len, ->>>>>>> origin/master )); -<<<<<<< HEAD #(serialize_fields)* - _serializer.serialize_struct_variant_end(state) - } -||||||| merged common ancestors - $serialize_fields - _serializer.serialize_struct_variant_end(state) - }).unwrap() -======= - $serialize_fields _serializer.serialize_struct_variant_end(__serde_state) - }).unwrap() ->>>>>>> origin/master + } } fn serialize_tuple_struct_visitor( @@ -528,19 +456,9 @@ fn serialize_tuple_struct_visitor( &structure_ty, generics, &field.ty, path, field_expr); } -<<<<<<< HEAD let ser = quote! { - try!(_serializer.#func(&mut state, #field_expr)); + try!(_serializer.#func(&mut __serde_state, #field_expr)); }; -||||||| merged common ancestors - let ser = quote_expr!(cx, - try!(_serializer.$func(&mut state, $field_expr)); - ); -======= - let ser = quote_expr!(cx, - try!(_serializer.$func(&mut __serde_state, $field_expr)); - ); ->>>>>>> origin/master match skip { None => ser, @@ -577,19 +495,9 @@ fn serialize_struct_visitor( &structure_ty, generics, &field.ty, path, field_expr) } -<<<<<<< HEAD let ser = quote! { - try!(_serializer.#func(&mut state, #key_expr, #field_expr)); + try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr)); }; -||||||| merged common ancestors - let ser = quote_expr!(cx, - try!(_serializer.$func(&mut state, $key_expr, $field_expr)); - ); -======= - let ser = quote_expr!(cx, - try!(_serializer.$func(&mut __serde_state, $key_expr, $field_expr)); - ); ->>>>>>> origin/master match skip { None => ser, From 8e77960e3a525531df4182c246da6f1df5ccaefa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 26 Sep 2016 23:17:33 -0700 Subject: [PATCH 034/111] Remove with-libsyntax feature --- serde_codegen/Cargo.toml | 1 - serde_codegen/src/lib.rs | 12 +++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 132547be..52bc9554 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -18,7 +18,6 @@ with-syntex = [ "syntex", "syntex_syntax", ] -with-libsyntax = [] with-syn = [] [dependencies] diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index fed63700..01b26699 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -2,7 +2,7 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", allow(too_many_arguments))] #![cfg_attr(feature = "clippy", allow(used_underscore_binding))] -#![cfg_attr(feature = "with-libsyntax", feature(rustc_private, plugin))] +#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))] // The `quote!` macro requires deep recursion. #![recursion_limit = "192"] @@ -16,11 +16,11 @@ extern crate syntex; #[macro_use] extern crate syntex_syntax as syntax; -#[cfg(feature = "with-libsyntax")] +#[cfg(not(feature = "with-syntex"))] #[macro_use] extern crate syntax; -#[cfg(feature = "with-libsyntax")] +#[cfg(not(feature = "with-syntex"))] extern crate rustc_plugin; extern crate syn; @@ -30,7 +30,7 @@ extern crate quote; #[cfg(feature = "with-syntex")] use std::path::Path; -#[cfg(feature = "with-libsyntax")] +#[cfg(not(feature = "with-syntex"))] use syntax::feature_gate::AttributeType; mod bound; @@ -104,7 +104,7 @@ pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> syntex::with_extra_stack(expand_thread) } -#[cfg(feature = "with-libsyntax")] +#[cfg(not(feature = "with-syntex"))] pub fn register(reg: &mut rustc_plugin::Registry) { reg.register_syntax_extension( syntax::parse::token::intern("derive_Serialize"), @@ -156,9 +156,7 @@ macro_rules! shim { }; } -#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] shim!(Serialize ser::expand_derive_serialize); -#[cfg(any(feature = "with-syntex", feature = "with-libsyntax"))] shim!(Deserialize de::expand_derive_deserialize); #[cfg(feature = "with-syn")] From 8ee8c070900a1720a0acdd89bcf60ffaf2e46350 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 26 Sep 2016 23:17:43 -0700 Subject: [PATCH 035/111] Mark all serde attributes as used --- serde_codegen/src/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 01b26699..150360ac 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -140,6 +140,20 @@ macro_rules! shim { } }; + use syntax::{attr, ast, visit}; + struct MarkSerdeAttributesUsed; + impl visit::Visitor for MarkSerdeAttributesUsed { + fn visit_attribute(&mut self, attr: &ast::Attribute) { + match attr.node.value.node { + ast::MetaItemKind::List(ref name, _) if name == "serde" => { + attr::mark_used(attr); + } + _ => {} + } + } + } + visit::walk_item(&mut MarkSerdeAttributesUsed, item); + use syntax::print::pprust; let s = pprust::item_to_string(item); From 4ad6c4fd56c6d06b27f3fa4362622e6575771a4a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 00:02:15 -0700 Subject: [PATCH 036/111] Include unknown attribute name in error message --- serde_codegen/Cargo.toml | 2 +- serde_codegen_internals/Cargo.toml | 2 +- serde_codegen_internals/src/attr.rs | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 52bc9554..0a4d6897 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -24,6 +24,6 @@ with-syn = [] clippy = { version = "^0.*", optional = true } quote = "0.1" serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } -syn = { version = "0.7", features = ["aster", "visit"] } +syn = { version = "0.7.1", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index f501786f..30534fde 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -15,4 +15,4 @@ unstable-testing = ["clippy"] [dependencies] clippy = { version = "^0.*", optional = true } -syn = "0.7" +syn = "0.7.1" diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 44da33e3..6ecbc8ad 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -142,8 +142,8 @@ impl Item { } _ => { - // TODO include name of attr - cx.error("unknown serde container attribute"); + cx.error(format!("unknown serde container attribute `{}`", + meta_item.name())); } } } @@ -208,8 +208,8 @@ impl Variant { } _ => { - // TODO include attribute - cx.error("unknown serde variant attribute"); + cx.error(format!("unknown serde variant attribute `{}`", + meta_item.name())); } } } @@ -353,8 +353,8 @@ impl Field { } _ => { - // TODO include attribute - cx.error("unknown serde field attribute"); + cx.error(format!("unknown serde field attribute `{}`", + meta_item.name())); } } } From 0c18c151e2d5186f22af69008629a20df687f6d8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 00:11:37 -0700 Subject: [PATCH 037/111] Revamp serde_codegen_internals error handling --- serde_codegen/src/de.rs | 7 +++--- serde_codegen/src/lib.rs | 18 ++++++++++----- serde_codegen/src/ser.rs | 10 +++++---- serde_codegen_internals/src/ctxt.rs | 34 ++++++++++++++++++++--------- serde_derive/src/lib.rs | 12 ++++++---- 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index d8a147d0..680c534b 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -5,11 +5,12 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Tokens { +pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Result { let item = { let ctxt = internals::Ctxt::new(); let item = Item::from_ast(&ctxt, item); check_no_str(&ctxt, &item); + try!(ctxt.check()); item }; @@ -27,7 +28,7 @@ pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Tokens { let dummy_const = aster::id(format!("_IMPL_DESERIALIZE_FOR_{}", item.ident)); - quote! { + Ok(quote! { #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const #dummy_const: () = { extern crate serde as _serde; @@ -40,7 +41,7 @@ pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Tokens { } } }; - } + }) } // All the generics in the input, plus a bound `T: Deserialize` for each generic diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 150360ac..9656016d 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -123,7 +123,7 @@ macro_rules! shim { ($name:ident $pkg:ident :: $func:ident) => { fn $func( cx: &mut ::syntax::ext::base::ExtCtxt, - _span: ::syntax::codemap::Span, + span: ::syntax::codemap::Span, meta_item: &::syntax::ast::MetaItem, annotatable: &::syntax::ext::base::Annotatable, push: &mut FnMut(::syntax::ext::base::Annotatable) @@ -158,7 +158,13 @@ macro_rules! shim { let s = pprust::item_to_string(item); let syn_item = syn::parse_macro_input(&s).unwrap(); - let expanded = $pkg::$func(&syn_item).to_string(); + let expanded = match $pkg::$func(&syn_item) { + Ok(expanded) => expanded.to_string(), + Err(msg) => { + cx.span_err(span, &msg); + return; + } + }; use syntax::parse; let name = stringify!($name).to_string(); @@ -174,21 +180,21 @@ shim!(Serialize ser::expand_derive_serialize); shim!(Deserialize de::expand_derive_deserialize); #[cfg(feature = "with-syn")] -pub fn expand_single_item(item: &str) -> String { +pub fn expand_single_item(item: &str) -> Result { let syn_item = syn::parse_macro_input(item).unwrap(); let (ser, de, syn_item) = strip_serde_derives(syn_item); let expanded_ser = if ser { - Some(ser::expand_derive_serialize(&syn_item)) + Some(try!(ser::expand_derive_serialize(&syn_item))) } else { None }; let expanded_de = if de { - Some(de::expand_derive_deserialize(&syn_item)) + Some(try!(de::expand_derive_deserialize(&syn_item))) } else { None:: }; let syn_item = strip_serde_attrs(syn_item); - return quote!(#expanded_ser #expanded_de #syn_item).to_string(); + return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string()); fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) { let mut ser = false; diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index de27e912..08aebb83 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -5,8 +5,10 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_serialize(item: &syn::MacroInput) -> Tokens { - let item = Item::from_ast(&internals::Ctxt::new(), item); +pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result { + let ctxt = internals::Ctxt::new(); + let item = Item::from_ast(&ctxt, item); + try!(ctxt.check()); let impl_generics = build_impl_generics(&item); @@ -22,7 +24,7 @@ pub fn expand_derive_serialize(item: &syn::MacroInput) -> Tokens { let dummy_const = aster::id(format!("_IMPL_SERIALIZE_FOR_{}", item.ident)); - quote! { + Ok(quote! { #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const #dummy_const: () = { extern crate serde as _serde; @@ -35,7 +37,7 @@ pub fn expand_derive_serialize(item: &syn::MacroInput) -> Tokens { } } }; - } + }) } // All the generics in the input, plus a bound `T: Serialize` for each generic diff --git a/serde_codegen_internals/src/ctxt.rs b/serde_codegen_internals/src/ctxt.rs index a516aec8..55ec5582 100644 --- a/serde_codegen_internals/src/ctxt.rs +++ b/serde_codegen_internals/src/ctxt.rs @@ -1,29 +1,43 @@ use std::fmt::Display; -use std::cell::Cell; +use std::cell::RefCell; #[derive(Default)] pub struct Ctxt { - err_count: Cell, + errors: RefCell>>, } impl Ctxt { pub fn new() -> Self { - Default::default() + Ctxt { + errors: RefCell::new(Some(Vec::new())), + } } pub fn error(&self, msg: T) { - println!("{}", msg); - self.err_count.set(self.err_count.get() + 1); + self.errors.borrow_mut().as_mut().unwrap().push(msg.to_string()); + } + + pub fn check(self) -> Result<(), String> { + let mut errors = self.errors.borrow_mut().take().unwrap(); + match errors.len() { + 0 => Ok(()), + 1 => Err(errors.pop().unwrap()), + n => { + let mut msg = format!("{} errors:", n); + for err in errors { + msg += "\n\t# "; + msg += &err; + } + Err(msg) + } + } } } impl Drop for Ctxt { fn drop(&mut self) { - let err_count = self.err_count.get(); - if err_count == 1 { - panic!("1 error"); - } else if err_count > 1 { - panic!("{} errors", err_count); + if self.errors.borrow().is_some() { + panic!("forgot to check for errors"); } } } diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 5c80708a..0f435142 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -9,13 +9,17 @@ use rustc_macro::TokenStream; #[rustc_macro_derive(Serialize)] pub fn derive_serialize(input: TokenStream) -> TokenStream { let item = format!("#[derive(Serialize)]\n{}", input); - let expanded = serde_codegen::expand_single_item(&item); - expanded.parse().unwrap() + match serde_codegen::expand_single_item(&item) { + Ok(expanded) => expanded.parse().unwrap(), + Err(msg) => panic!(msg), + } } #[rustc_macro_derive(Deserialize)] pub fn derive_deserialize(input: TokenStream) -> TokenStream { let item = format!("#[derive(Deserialize)]\n{}", input); - let expanded = serde_codegen::expand_single_item(&item); - expanded.parse().unwrap() + match serde_codegen::expand_single_item(&item) { + Ok(expanded) => expanded.parse().unwrap(), + Err(msg) => panic!(msg), + } } From 40b874214a3a9b64181211b3fa28f290ca973366 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 00:17:00 -0700 Subject: [PATCH 038/111] Update tests to new location of errors --- .../tests/compile-fail/duplicate_attributes.rs | 14 +++++++------- .../compile-fail/reject-unknown-attributes.rs | 16 ++++++++-------- serde_macros/tests/compile-fail/str_ref_deser.rs | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/serde_macros/tests/compile-fail/duplicate_attributes.rs b/serde_macros/tests/compile-fail/duplicate_attributes.rs index 4c1caab2..61c98697 100644 --- a/serde_macros/tests/compile-fail/duplicate_attributes.rs +++ b/serde_macros/tests/compile-fail/duplicate_attributes.rs @@ -1,14 +1,14 @@ #![feature(custom_attribute, custom_derive, plugin)] #![plugin(serde_macros)] -#[derive(Serialize)] +#[derive(Serialize)] //~ ERROR: 6 errors: struct S { #[serde(rename(serialize="x"))] - #[serde(rename(serialize="y"))] //~ ERROR: duplicate serde attribute `rename` + #[serde(rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` a: (), #[serde(rename(serialize="x"))] - #[serde(rename="y")] //~ ERROR: duplicate serde attribute `rename` + #[serde(rename="y")] // ERROR: duplicate serde attribute `rename` b: (), #[serde(rename(serialize="x"))] @@ -16,16 +16,16 @@ struct S { c: (), #[serde(rename="x")] - #[serde(rename(deserialize="y"))] //~ ERROR: duplicate serde attribute `rename` + #[serde(rename(deserialize="y"))] // ERROR: duplicate serde attribute `rename` d: (), - #[serde(rename(serialize="x", serialize="y"))] //~ ERROR: duplicate serde attribute `rename` + #[serde(rename(serialize="x", serialize="y"))] // ERROR: duplicate serde attribute `rename` e: (), - #[serde(rename="x", serialize="y")] //~ ERROR: unknown serde field attribute `serialize = "y"` + #[serde(rename="x", serialize="y")] // ERROR: unknown serde field attribute `serialize` f: (), - #[serde(rename(serialize="x"), rename(serialize="y"))] //~ ERROR: duplicate serde attribute `rename` + #[serde(rename(serialize="x"), rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` g: (), } diff --git a/serde_macros/tests/compile-fail/reject-unknown-attributes.rs b/serde_macros/tests/compile-fail/reject-unknown-attributes.rs index 5a4d2776..9c71fae7 100644 --- a/serde_macros/tests/compile-fail/reject-unknown-attributes.rs +++ b/serde_macros/tests/compile-fail/reject-unknown-attributes.rs @@ -3,27 +3,27 @@ extern crate serde; -#[derive(Serialize)] -#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"` +#[derive(Serialize)] //~ unknown serde container attribute `abc` +#[serde(abc="xyz")] struct Foo { x: u32, } -#[derive(Deserialize)] -#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"` +#[derive(Deserialize)] //~ unknown serde container attribute `abc` +#[serde(abc="xyz")] struct Foo { x: u32, } -#[derive(Serialize)] +#[derive(Serialize)] //~ unknown serde field attribute `abc` struct Foo { - #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"` + #[serde(abc="xyz")] x: u32, } -#[derive(Deserialize)] +#[derive(Deserialize)] //~ unknown serde field attribute `abc` struct Foo { - #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"` + #[serde(abc="xyz")] x: u32, } diff --git a/serde_macros/tests/compile-fail/str_ref_deser.rs b/serde_macros/tests/compile-fail/str_ref_deser.rs index 827d08c9..610ed680 100644 --- a/serde_macros/tests/compile-fail/str_ref_deser.rs +++ b/serde_macros/tests/compile-fail/str_ref_deser.rs @@ -1,9 +1,9 @@ #![feature(custom_attribute, custom_derive, plugin)] #![plugin(serde_macros)] -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize)] //~ ERROR: Serde does not support deserializing fields of type &str struct Test<'a> { - s: &'a str, //~ ERROR: Serde does not support deserializing fields of type &str + s: &'a str, } fn main() {} From 7e441e5110d69da8751d6480ccd4c7c74b6d7334 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 00:40:37 -0700 Subject: [PATCH 039/111] Handle various attribute parsing error cases --- serde_codegen_internals/src/attr.rs | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 6ecbc8ad..2f90328d 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -1,5 +1,5 @@ use Ctxt; -use syn::{self, Ident}; +use syn; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints // are `attr::Item::from_ast`, `attr::Variant::from_ast`, and @@ -106,7 +106,7 @@ impl Item { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - if let Ok(s) = get_string_from_lit(cx, name, lit) { + if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); } @@ -127,7 +127,7 @@ impl Item { // Parse `#[serde(bound="D: Serialize")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => { - if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) { + if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { ser_bound.set(where_predicates.clone()); de_bound.set(where_predicates); } @@ -193,7 +193,7 @@ impl Variant { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - if let Ok(s) = get_string_from_lit(cx, name, lit) { + if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); } @@ -279,7 +279,7 @@ impl Field { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - if let Ok(s) = get_string_from_lit(cx, name, lit) { + if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); } @@ -300,7 +300,7 @@ impl Field { // Parse `#[serde(default="...")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "default" => { - if let Ok(path) = parse_lit_into_path(cx, name, lit) { + if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { default.set(FieldDefault::Path(path)); } } @@ -317,28 +317,28 @@ impl Field { // Parse `#[serde(skip_serializing_if="...")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "skip_serializing_if" => { - if let Ok(path) = parse_lit_into_path(cx, name, lit) { + if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { skip_serializing_if.set(path); } } // Parse `#[serde(serialize_with="...")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize_with" => { - if let Ok(path) = parse_lit_into_path(cx, name, lit) { + if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { serialize_with.set(path); } } // Parse `#[serde(deserialize_with="...")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize_with" => { - if let Ok(path) = parse_lit_into_path(cx, name, lit) { + if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { deserialize_with.set(path); } } // Parse `#[serde(bound="D: Serialize")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => { - if let Ok(where_predicates) = parse_lit_into_where(cx, name, lit) { + if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { ser_bound.set(where_predicates.clone()); de_bound.set(where_predicates); } @@ -423,31 +423,32 @@ type SerAndDe = (Option, Option); fn get_ser_and_de( cx: &Ctxt, - attribute: &'static str, + attr_name: &'static str, items: &[syn::MetaItem], f: F ) -> Result, ()> - where F: Fn(&Ctxt, &Ident, &syn::Lit) -> Result, + where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result, { - let mut ser_item = Attr::none(cx, attribute); - let mut de_item = Attr::none(cx, attribute); + let mut ser_item = Attr::none(cx, attr_name); + let mut de_item = Attr::none(cx, attr_name); for item in items { match *item { syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize" => { - if let Ok(v) = f(cx, name, lit) { + if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) { ser_item.set(v); } } syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize" => { - if let Ok(v) = f(cx, name, lit) { + if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) { de_item.set(v); } } _ => { - cx.error(format!("bad {} attribute", attribute)); + cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", + attr_name)); return Err(()); } } @@ -479,29 +480,28 @@ pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> } } -fn get_string_from_lit(_cx: &Ctxt, _name: &Ident, lit: &syn::Lit) -> Result { +fn get_string_from_lit(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result { if let syn::Lit::Str(ref s, _) = *lit { Ok(s.clone()) } else { - // TODO handle error + cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`", + attr_name, meta_item_name)); Err(()) } } -fn parse_lit_into_path(cx: &Ctxt, name: &Ident, lit: &syn::Lit) -> Result { - let string = try!(get_string_from_lit(cx, name, lit)); - // TODO handle error - Ok(syn::parse_path(&string).unwrap()) +fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result { + let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit)); + syn::parse_path(&string).map_err(|err| cx.error(err)) } -fn parse_lit_into_where(cx: &Ctxt, name: &Ident, lit: &syn::Lit) -> Result, ()> { - let string = try!(get_string_from_lit(cx, name, lit)); +fn parse_lit_into_where(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result, ()> { + let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit)); if string.is_empty() { return Ok(Vec::new()); } let where_string = format!("where {}", string); - // TODO handle error - Ok(syn::parse_where_clause(&where_string).unwrap().predicates) + syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err)) } From 7d09b1475c88c2890f194b05af6319a27bf72504 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 00:46:03 -0700 Subject: [PATCH 040/111] Fix clippy lints in serde_codegen --- serde_codegen/src/de.rs | 21 ++++++++++----------- serde_codegen/src/ser.rs | 10 +++++----- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 680c534b..dd97407f 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -62,10 +62,9 @@ fn build_impl_generics(item: &Item) -> syn::Generics { let generics = bound::with_bound(item, &generics, needs_deserialize_bound, &aster::path().ids(&["_serde", "de", "Deserialize"]).build()); - let generics = bound::with_bound(item, &generics, + bound::with_bound(item, &generics, requires_default, - &aster::path().global().ids(&["std", "default", "Default"]).build()); - generics + &aster::path().global().ids(&["std", "default", "Default"]).build()) } } } @@ -325,7 +324,7 @@ fn deserialize_seq( } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - type_ident, impl_generics, &field.ty, path); + type_ident, impl_generics, field.ty, path); quote!({ #wrapper #wrapper_impl @@ -390,7 +389,7 @@ fn deserialize_newtype_struct( } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - type_ident, impl_generics, &field.ty, path); + type_ident, impl_generics, field.ty, path); quote!({ #wrapper #wrapper_impl @@ -421,7 +420,7 @@ fn deserialize_struct( let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics); let type_path = match variant_ident { - Some(ref variant_ident) => quote!(#type_ident::#variant_ident), + Some(variant_ident) => quote!(#type_ident::#variant_ident), None => quote!(#type_ident), }; @@ -580,7 +579,7 @@ fn deserialize_variant( Style::Newtype => { deserialize_newtype_variant( type_ident, - &variant_ident, + variant_ident, generics, &variant.fields[0], ) @@ -621,7 +620,7 @@ fn deserialize_newtype_variant( } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - type_ident, impl_generics, &field.ty, path); + type_ident, impl_generics, field.ty, path); quote!({ #wrapper #wrapper_impl @@ -719,7 +718,7 @@ fn deserialize_field_visitor( // Match arms to extract a field from a string let bytes_field_arms: Vec<_> = field_idents.iter().zip(field_names.iter()) .map(|(field_ident, field_name)| { - let bytes_field_name = quote::ByteStr(&field_name); + let bytes_field_name = quote::ByteStr(field_name); quote! { #bytes_field_name => { Ok(__Field::#field_ident) } } @@ -849,7 +848,7 @@ fn deserialize_map( // Match arms to extract a value for a field. let value_arms = fields_names.iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) - .map(|&(ref field, ref name)| { + .map(|&(field, ref name)| { let deser_name = field.attrs.name().deserialize_name(); let visit = match field.attrs.deserialize_with() { @@ -861,7 +860,7 @@ fn deserialize_map( } Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( - type_ident, impl_generics, &field.ty, path); + type_ident, impl_generics, field.ty, path); quote!({ #wrapper #wrapper_impl diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 08aebb83..bb1c1089 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -140,7 +140,7 @@ fn serialize_newtype_struct( let mut field_expr = quote!(&self.0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_with( - &item_ty, impl_generics, &field.ty, path, field_expr); + &item_ty, impl_generics, field.ty, path, field_expr); } quote! { @@ -342,7 +342,7 @@ fn serialize_newtype_variant( let mut field_expr = quote!(__simple_value); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_with( - &item_ty, generics, &field.ty, path, field_expr); + &item_ty, generics, field.ty, path, field_expr); } quote! { @@ -397,7 +397,7 @@ fn serialize_struct_variant( let serialize_fields = serialize_struct_visitor( ty.clone(), fields, - &generics, + generics, true, aster::id("serialize_struct_variant_elt"), ); @@ -455,7 +455,7 @@ fn serialize_tuple_struct_visitor( if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_with( - &structure_ty, generics, &field.ty, path, field_expr); + &structure_ty, generics, field.ty, path, field_expr); } let ser = quote! { @@ -494,7 +494,7 @@ fn serialize_struct_visitor( if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_with( - &structure_ty, generics, &field.ty, path, field_expr) + &structure_ty, generics, field.ty, path, field_expr) } let ser = quote! { From 9a86e6818f2e3c92ffb15b2fd0e768243bfc4d43 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 00:47:54 -0700 Subject: [PATCH 041/111] Use push_str to support old compilers --- serde_codegen_internals/src/ctxt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_codegen_internals/src/ctxt.rs b/serde_codegen_internals/src/ctxt.rs index 55ec5582..a1455332 100644 --- a/serde_codegen_internals/src/ctxt.rs +++ b/serde_codegen_internals/src/ctxt.rs @@ -25,8 +25,8 @@ impl Ctxt { n => { let mut msg = format!("{} errors:", n); for err in errors { - msg += "\n\t# "; - msg += &err; + msg.push_str("\n\t# "); + msg.push_str(&err); } Err(msg) } From effa298871f5a21231fa5c68b24d92cc70c67f3a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 01:04:11 -0700 Subject: [PATCH 042/111] Fix differences in the generated code --- serde_codegen/Cargo.toml | 4 ++-- serde_codegen/src/de.rs | 31 +++++++++++++++++------------- serde_codegen/src/ser.rs | 21 +++++++++++++++----- serde_codegen_internals/Cargo.toml | 2 +- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 0a4d6897..56eb6bcc 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,8 +22,8 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } -quote = "0.1" +quote = "0.2" serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } -syn = { version = "0.7.1", features = ["aster", "visit"] } +syn = { version = "0.8", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index dd97407f..398f6422 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -36,9 +36,7 @@ pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Result(deserializer: &mut __D) -> ::std::result::Result<#ty, __D::Error> where __D: _serde::de::Deserializer - { - #body - } + #body } }; }) @@ -151,6 +149,8 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) { quote!(__Visitor), ) } else { + let where_clause = &generics.where_clause; + let num_phantoms = generics.lifetimes.len() + generics.ty_params.len(); let phantom_types = generics.lifetimes.iter() @@ -190,7 +190,7 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) { ( quote! { - struct __Visitor #generics ( #(phantom_types),* ); + struct __Visitor #generics ( #(phantom_types),* ) #where_clause; }, quote!(__Visitor <#(all_params),*> ), quote!(__Visitor #ty_param_idents ( #(phantom_exprs),* )), @@ -204,7 +204,7 @@ fn deserialize_unit_struct( ) -> Tokens { let type_name = item_attrs.name().deserialize_name(); - quote! { + quote!({ struct __Visitor; impl _serde::de::Visitor for __Visitor { @@ -227,7 +227,7 @@ fn deserialize_unit_struct( } deserializer.deserialize_unit_struct(#type_name, __Visitor) - } + }) } fn deserialize_tuple( @@ -537,7 +537,7 @@ fn deserialize_item_enum( let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics); - quote! { + quote!({ #variant_visitor #visitor_item @@ -557,7 +557,7 @@ fn deserialize_item_enum( #variants_stmt deserializer.deserialize_enum(#type_name, VARIANTS, #visitor_expr) - } + }) } fn deserialize_variant( @@ -628,9 +628,11 @@ fn deserialize_newtype_variant( }) } }; - quote! { - Ok(#type_ident::#variant_ident(#visit)), - } + // The outer braces are unnecessary but quasi used to have them. We can + // remove them separately from the syn conversion. + quote!({ + Ok(#type_ident::#variant_ident(#visit)) + }) } fn deserialize_field_visitor( @@ -861,11 +863,14 @@ fn deserialize_map( Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( type_ident, impl_generics, field.ty, path); - quote!({ + // The outer parentheses are redundant but quasi used to put + // them in. We can remove them separately from the syn + // conversion. + quote!(({ #wrapper #wrapper_impl try!(visitor.visit_value::<#wrapper_ty>()).value - }) + })) } }; quote! { diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index bb1c1089..57d85fb7 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -279,7 +279,9 @@ fn serialize_variant( ); quote! { - #type_ident::#variant_ident(ref __simple_value) => #block, + // The braces are unnecessary but quasi used to put them in. We + // can remove them separately from the syn conversion. + #type_ident::#variant_ident(ref __simple_value) => { #block }, } }, Style::Tuple => { @@ -447,6 +449,7 @@ fn serialize_tuple_struct_visitor( let id = aster::id(format!("__field{}", i)); quote!(#id) } else { + let i = aster::id(i); quote!(&self.#i) }; @@ -459,11 +462,15 @@ fn serialize_tuple_struct_visitor( } let ser = quote! { - try!(_serializer.#func(&mut __serde_state, #field_expr)); + // This line should end in a semicolon but quasi used to behave + // differently between skipped and non-skipped so I have + // preserved that behavior. We can update it separately from the + // syn conversion. + try!(_serializer.#func(&mut __serde_state, #field_expr)) }; match skip { - None => ser, + None => quote!(#ser;), Some(skip) => quote!(if !#skip { #ser }), } }) @@ -498,11 +505,15 @@ fn serialize_struct_visitor( } let ser = quote! { - try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr)); + // This line should end in a semicolon but quasi used to behave + // differently between skipped and non-skipped so I have + // preserved that behavior. We can update it separately from the + // syn conversion. + try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr)) }; match skip { - None => ser, + None => quote!(#ser;), Some(skip) => quote!(if !#skip { #ser }), } }) diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 30534fde..8d14d7bf 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -15,4 +15,4 @@ unstable-testing = ["clippy"] [dependencies] clippy = { version = "^0.*", optional = true } -syn = "0.7.1" +syn = "0.8" From 9fe16767c53407d82a389ccabaeaa29891c10065 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 28 Sep 2016 08:57:53 -0700 Subject: [PATCH 043/111] Use iter::repeat to build phantom exprs --- serde_codegen/src/de.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 398f6422..dfe84398 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -5,6 +5,8 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; +use std::iter; + pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Result { let item = { let ctxt = internals::Ctxt::new(); @@ -186,7 +188,7 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) { Some(quote!(::<#(ty_param_idents),*>)) }; - let phantom_exprs = (0 .. num_phantoms).map(|_| quote!(::std::marker::PhantomData)); + let phantom_exprs = iter::repeat(quote!(::std::marker::PhantomData)).take(num_phantoms); ( quote! { From 554b81d636adbfff787e71e1b2e66f565d636bed Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 28 Sep 2016 09:25:19 -0700 Subject: [PATCH 044/111] Fix compiletest error in newest nightly --- .../tests/compile-fail/reject-unknown-attributes.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/serde_macros/tests/compile-fail/reject-unknown-attributes.rs b/serde_macros/tests/compile-fail/reject-unknown-attributes.rs index 5a4d2776..e5d296b0 100644 --- a/serde_macros/tests/compile-fail/reject-unknown-attributes.rs +++ b/serde_macros/tests/compile-fail/reject-unknown-attributes.rs @@ -5,24 +5,24 @@ extern crate serde; #[derive(Serialize)] #[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"` -struct Foo { +struct A { x: u32, } #[derive(Deserialize)] #[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"` -struct Foo { +struct B { x: u32, } #[derive(Serialize)] -struct Foo { +struct C { #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"` x: u32, } #[derive(Deserialize)] -struct Foo { +struct D { #[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"` x: u32, } From 6ccb6c9130974230c713612482737521fa0cbfb3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 28 Sep 2016 09:18:18 -0700 Subject: [PATCH 045/111] Clean up syn workarounds --- serde_codegen/src/de.rs | 15 ++++------- serde_codegen/src/ser.rs | 54 ++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index dfe84398..ec2f9026 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -630,11 +630,9 @@ fn deserialize_newtype_variant( }) } }; - // The outer braces are unnecessary but quasi used to have them. We can - // remove them separately from the syn conversion. - quote!({ - Ok(#type_ident::#variant_ident(#visit)) - }) + quote! { + Ok(#type_ident::#variant_ident(#visit)), + } } fn deserialize_field_visitor( @@ -865,14 +863,11 @@ fn deserialize_map( Some(path) => { let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( type_ident, impl_generics, field.ty, path); - // The outer parentheses are redundant but quasi used to put - // them in. We can remove them separately from the syn - // conversion. - quote!(({ + quote!({ #wrapper #wrapper_impl try!(visitor.visit_value::<#wrapper_ty>()).value - })) + }) } }; quote! { diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 57d85fb7..0bbcd7e9 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -279,9 +279,7 @@ fn serialize_variant( ); quote! { - // The braces are unnecessary but quasi used to put them in. We - // can remove them separately from the syn conversion. - #type_ident::#variant_ident(ref __simple_value) => { #block }, + #type_ident::#variant_ident(ref __simple_value) => #block, } }, Style::Tuple => { @@ -462,15 +460,11 @@ fn serialize_tuple_struct_visitor( } let ser = quote! { - // This line should end in a semicolon but quasi used to behave - // differently between skipped and non-skipped so I have - // preserved that behavior. We can update it separately from the - // syn conversion. - try!(_serializer.#func(&mut __serde_state, #field_expr)) + try!(_serializer.#func(&mut __serde_state, #field_expr)); }; match skip { - None => quote!(#ser;), + None => ser, Some(skip) => quote!(if !#skip { #ser }), } }) @@ -505,15 +499,11 @@ fn serialize_struct_visitor( } let ser = quote! { - // This line should end in a semicolon but quasi used to behave - // differently between skipped and non-skipped so I have - // preserved that behavior. We can update it separately from the - // syn conversion. - try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr)) + try!(_serializer.#func(&mut __serde_state, #key_expr, #field_expr)); }; match skip { - None => quote!(#ser;), + None => ser, Some(skip) => quote!(if !#skip { #ser }), } }) @@ -540,27 +530,25 @@ fn wrap_serialize_with( .build() .build(); - quote! { - { - struct __SerializeWith #wrapper_generics #where_clause { - value: &'__a #field_ty, - phantom: ::std::marker::PhantomData<#item_ty>, - } + quote!({ + struct __SerializeWith #wrapper_generics #where_clause { + value: &'__a #field_ty, + phantom: ::std::marker::PhantomData<#item_ty>, + } - impl #wrapper_generics _serde::ser::Serialize for #wrapper_ty #where_clause { - fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error> - where __S: _serde::ser::Serializer - { - #path(self.value, __s) - } - } - - __SerializeWith { - value: #value, - phantom: ::std::marker::PhantomData::<#item_ty>, + impl #wrapper_generics _serde::ser::Serialize for #wrapper_ty #where_clause { + fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error> + where __S: _serde::ser::Serializer + { + #path(self.value, __s) } } - } + + __SerializeWith { + value: #value, + phantom: ::std::marker::PhantomData::<#item_ty>, + } + }) } // Serialization of an empty struct results in code like: From 2a2c098eeb147890e04c348e108e26a93fe57d8b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 27 Sep 2016 22:22:28 -0700 Subject: [PATCH 046/111] Release 0.8.10 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 4 ++-- serde_codegen_internals/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 29765444..f3db9bc7 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.9" +version = "0.8.10" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 56eb6bcc..a4ed927c 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.9" +version = "0.8.10" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,7 +23,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } quote = "0.2" -serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } +serde_codegen_internals = { version = "=0.9.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.8", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 8d14d7bf..5213aeaf 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.8.9" +version = "0.9.0" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index c7425c2c..51985b25 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.9" +version = "0.8.10" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,12 +15,12 @@ name = "serde_derive" rustc-macro = true [dependencies.serde_codegen] -version = "=0.8.9" +version = "=0.8.10" path = "../serde_codegen" default-features = false features = ["with-syn"] [dev-dependencies] fnv = "1.0" -serde = { version = "0.8.9", path = "../serde" } -serde_test = { version = "0.8.9", path = "../serde_test" } +serde = { version = "0.8.10", path = "../serde" } +serde_test = { version = "0.8.10", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index a0d9ab65..aa7eb3a1 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.9" +version = "0.8.10" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.9", path = "../serde" } +serde = { version = "0.8.10", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 03a8ab4a..9110b079 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.9" +version = "0.8.10" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 8b7b886036c5a58aa9b30e777612ef0f1c4f6d7a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 28 Sep 2016 11:19:27 -0700 Subject: [PATCH 047/111] Test serde_derive instead of serde_macros --- .travis.yml | 2 +- examples/serde-syntex-example/Cargo.toml | 4 ++-- examples/serde-syntex-example/build.rs | 4 ++-- examples/serde-syntex-example/src/main.rs | 11 +++++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1140ebdc..825b6a07 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ script: - (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections) - (cd testing && travis-cargo --skip nightly test) - (cd testing && travis-cargo --only nightly test -- --features unstable-testing) -- (cd serde_macros && travis-cargo --only nightly test -- --features unstable-testing) +- (cd serde_derive && travis-cargo --only nightly test) - (cd examples/serde-syntex-example && travis-cargo --skip nightly run) - (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable) - (cd serde && travis-cargo --only stable doc) diff --git a/examples/serde-syntex-example/Cargo.toml b/examples/serde-syntex-example/Cargo.toml index 97de0a37..9a150821 100644 --- a/examples/serde-syntex-example/Cargo.toml +++ b/examples/serde-syntex-example/Cargo.toml @@ -6,12 +6,12 @@ build = "build.rs" [features] default = ["serde_codegen"] -unstable = ["serde_macros"] +unstable = ["serde_derive"] [build-dependencies] serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" } [dependencies] serde = "^0.8" +serde_derive = { version = "^0.8", optional = true, path = "../../serde_derive" } serde_json = "^0.8" -serde_macros = { version = "^0.8", optional = true, path = "../../serde_macros" } diff --git a/examples/serde-syntex-example/build.rs b/examples/serde-syntex-example/build.rs index 48728b8b..c775d665 100644 --- a/examples/serde-syntex-example/build.rs +++ b/examples/serde-syntex-example/build.rs @@ -1,4 +1,4 @@ -#[cfg(not(feature = "serde_macros"))] +#[cfg(not(feature = "serde_derive"))] mod inner { extern crate serde_codegen; @@ -15,7 +15,7 @@ mod inner { } } -#[cfg(feature = "serde_macros")] +#[cfg(feature = "serde_derive")] mod inner { pub fn main() {} } diff --git a/examples/serde-syntex-example/src/main.rs b/examples/serde-syntex-example/src/main.rs index 0a8804ab..46e7d1dc 100644 --- a/examples/serde-syntex-example/src/main.rs +++ b/examples/serde-syntex-example/src/main.rs @@ -1,11 +1,14 @@ -#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))] -#![cfg_attr(feature = "serde_macros", plugin(serde_macros))] +#![cfg_attr(feature = "serde_derive", feature(rustc_macro))] + +#[cfg(feature = "serde_derive")] +#[macro_use] +extern crate serde_derive; extern crate serde; extern crate serde_json; -#[cfg(feature = "serde_macros")] +#[cfg(feature = "serde_derive")] include!("main.rs.in"); -#[cfg(not(feature = "serde_macros"))] +#[cfg(not(feature = "serde_derive"))] include!(concat!(env!("OUT_DIR"), "/main.rs")); From 1b6fd5a362ae1925153213ab329678a4ce2e2ce4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 28 Sep 2016 09:55:54 -0700 Subject: [PATCH 048/111] Delete serde_macros --- serde_derive/Cargo.toml | 1 + .../duplicate-attribute/rename-and-ser.rs | 12 ++++++ .../duplicate-attribute/rename-rename-de.rs | 13 ++++++ .../rename-ser-rename-ser.rs | 12 ++++++ .../duplicate-attribute/rename-ser-rename.rs | 13 ++++++ .../duplicate-attribute/rename-ser-ser.rs | 12 ++++++ .../duplicate-attribute/two-rename-ser.rs | 13 ++++++ .../tests/compile-fail/str_ref_deser.rs | 11 +++++ .../unknown-attribute/container.rs | 12 ++++++ .../compile-fail/unknown-attribute/field.rs | 12 ++++++ .../compile-fail/unknown-attribute/variant.rs | 12 ++++++ .../tests/compile_tests.rs | 0 .../tests/run-pass/identity-op.rs | 7 ++-- serde_derive/tests/test.rs | 2 + serde_macros/.cargo/config | 2 - serde_macros/.gitignore | 2 - serde_macros/Cargo.toml | 41 ------------------- serde_macros/benches/bench.rs | 9 ---- serde_macros/src/lib.rs | 12 ------ .../compile-fail/duplicate_attributes.rs | 32 --------------- .../compile-fail/reject-unknown-attributes.rs | 30 -------------- .../tests/compile-fail/str_ref_deser.rs | 9 ---- serde_macros/tests/test.rs | 8 ---- 23 files changed, 129 insertions(+), 148 deletions(-) create mode 100644 serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs create mode 100644 serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs create mode 100644 serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs create mode 100644 serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs create mode 100644 serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs create mode 100644 serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs create mode 100644 serde_derive/tests/compile-fail/str_ref_deser.rs create mode 100644 serde_derive/tests/compile-fail/unknown-attribute/container.rs create mode 100644 serde_derive/tests/compile-fail/unknown-attribute/field.rs create mode 100644 serde_derive/tests/compile-fail/unknown-attribute/variant.rs rename {serde_macros => serde_derive}/tests/compile_tests.rs (100%) rename {serde_macros => serde_derive}/tests/run-pass/identity-op.rs (80%) delete mode 100644 serde_macros/.cargo/config delete mode 100644 serde_macros/.gitignore delete mode 100644 serde_macros/Cargo.toml delete mode 100644 serde_macros/benches/bench.rs delete mode 100644 serde_macros/src/lib.rs delete mode 100644 serde_macros/tests/compile-fail/duplicate_attributes.rs delete mode 100644 serde_macros/tests/compile-fail/reject-unknown-attributes.rs delete mode 100644 serde_macros/tests/compile-fail/str_ref_deser.rs delete mode 100644 serde_macros/tests/test.rs diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 51985b25..32960964 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -21,6 +21,7 @@ default-features = false features = ["with-syn"] [dev-dependencies] +compiletest_rs = "^0.2.0" fnv = "1.0" serde = { version = "0.8.10", path = "../serde" } serde_test = { version = "0.8.10", path = "../serde_test" } diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs new file mode 100644 index 00000000..4a6590aa --- /dev/null +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs @@ -0,0 +1,12 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct S { + #[serde(rename="x", serialize="y")] // ERROR: unknown serde field attribute `serialize` + x: (), +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs new file mode 100644 index 00000000..21a31b6c --- /dev/null +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs @@ -0,0 +1,13 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct S { + #[serde(rename="x")] + #[serde(rename(deserialize="y"))] // ERROR: duplicate serde attribute `rename` + x: (), +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs new file mode 100644 index 00000000..be64ec03 --- /dev/null +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs @@ -0,0 +1,12 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct S { + #[serde(rename(serialize="x"), rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` + x: (), +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs new file mode 100644 index 00000000..1dd2a982 --- /dev/null +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs @@ -0,0 +1,13 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct S { + #[serde(rename(serialize="x"))] + #[serde(rename="y")] // ERROR: duplicate serde attribute `rename` + x: (), +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs new file mode 100644 index 00000000..ef9a7c5c --- /dev/null +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs @@ -0,0 +1,12 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct S { + #[serde(rename(serialize="x", serialize="y"))] // ERROR: duplicate serde attribute `rename` + x: (), +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs new file mode 100644 index 00000000..35e9a5a0 --- /dev/null +++ b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs @@ -0,0 +1,13 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct S { + #[serde(rename(serialize="x"))] + #[serde(rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` + x: (), +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/str_ref_deser.rs b/serde_derive/tests/compile-fail/str_ref_deser.rs new file mode 100644 index 00000000..98c21617 --- /dev/null +++ b/serde_derive/tests/compile-fail/str_ref_deser.rs @@ -0,0 +1,11 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize, Deserialize)] //~ ERROR: custom derive attribute panicked +struct Test<'a> { + s: &'a str, // ERROR: Serde does not support deserializing fields of type &str +} + +fn main() {} diff --git a/serde_derive/tests/compile-fail/unknown-attribute/container.rs b/serde_derive/tests/compile-fail/unknown-attribute/container.rs new file mode 100644 index 00000000..1815a7ce --- /dev/null +++ b/serde_derive/tests/compile-fail/unknown-attribute/container.rs @@ -0,0 +1,12 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +#[serde(abc="xyz")] // ERROR: unknown serde container attribute `abc` +struct A { + x: u32, +} + +fn main() { } diff --git a/serde_derive/tests/compile-fail/unknown-attribute/field.rs b/serde_derive/tests/compile-fail/unknown-attribute/field.rs new file mode 100644 index 00000000..5cc6372c --- /dev/null +++ b/serde_derive/tests/compile-fail/unknown-attribute/field.rs @@ -0,0 +1,12 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +struct C { + #[serde(abc="xyz")] // ERROR: unknown serde field attribute `abc` + x: u32, +} + +fn main() { } diff --git a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs new file mode 100644 index 00000000..353ef91f --- /dev/null +++ b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs @@ -0,0 +1,12 @@ +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; + +#[derive(Serialize)] //~ ERROR: custom derive attribute panicked +enum E { + #[serde(abc="xyz")] // ERROR: unknown serde variant attribute `abc` + V, +} + +fn main() { } diff --git a/serde_macros/tests/compile_tests.rs b/serde_derive/tests/compile_tests.rs similarity index 100% rename from serde_macros/tests/compile_tests.rs rename to serde_derive/tests/compile_tests.rs diff --git a/serde_macros/tests/run-pass/identity-op.rs b/serde_derive/tests/run-pass/identity-op.rs similarity index 80% rename from serde_macros/tests/run-pass/identity-op.rs rename to serde_derive/tests/run-pass/identity-op.rs index dcf8117a..47e2c750 100644 --- a/serde_macros/tests/run-pass/identity-op.rs +++ b/serde_derive/tests/run-pass/identity-op.rs @@ -1,8 +1,9 @@ -#![feature(custom_derive, plugin)] -#![plugin(serde_macros, clippy)] - +#![feature(rustc_macro)] #![deny(identity_op)] +#[macro_use] +extern crate serde_derive; + // The derived implementation uses 0+1 to add up the number of fields // serialized, which Clippy warns about. If the expansion info is registered // correctly, the Clippy lint is not triggered. diff --git a/serde_derive/tests/test.rs b/serde_derive/tests/test.rs index ff8ac572..80239edf 100644 --- a/serde_derive/tests/test.rs +++ b/serde_derive/tests/test.rs @@ -6,3 +6,5 @@ extern crate serde_derive; extern crate test; include!("../../testing/tests/test.rs.in"); + +mod compile_tests; diff --git a/serde_macros/.cargo/config b/serde_macros/.cargo/config deleted file mode 100644 index 7f1ab8d3..00000000 --- a/serde_macros/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -# To prevent compiletest from seeing two versions of serde -paths = ["../serde"] diff --git a/serde_macros/.gitignore b/serde_macros/.gitignore deleted file mode 100644 index 4fffb2f8..00000000 --- a/serde_macros/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -/Cargo.lock diff --git a/serde_macros/Cargo.toml b/serde_macros/Cargo.toml deleted file mode 100644 index 62b5e682..00000000 --- a/serde_macros/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "serde_macros" -version = "0.8.9" -authors = ["Erick Tryzelaar "] -license = "MIT/Apache-2.0" -description = "Macros to auto-generate implementations for the serde framework" -homepage = "https://serde.rs" -repository = "https://github.com/serde-rs/serde" -documentation = "https://serde.rs/codegen.html" -keywords = ["serde", "serialization"] -include = ["Cargo.toml", "src/**/*.rs"] - -[lib] -name = "serde_macros" -plugin = true - -[features] -unstable-testing = [ - "clippy", - "serde/unstable-testing", - "serde_codegen/unstable-testing" -] - -[dependencies] -clippy = { version = "^0.*", optional = true } -serde_codegen = { version = "=0.8.9", default-features = false, features = ["unstable"], path = "../serde_codegen" } - -[dev-dependencies] -compiletest_rs = "^0.2.0" -fnv = "1.0" -rustc-serialize = "^0.3.16" -serde = { version = "0.8.9", path = "../serde" } -serde_test = { version = "0.8.9", path = "../serde_test" } - -[[test]] -name = "test" -path = "tests/test.rs" - -[[bench]] -name = "bench" -path = "benches/bench.rs" diff --git a/serde_macros/benches/bench.rs b/serde_macros/benches/bench.rs deleted file mode 100644 index ec15c18c..00000000 --- a/serde_macros/benches/bench.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(custom_attribute, custom_derive, plugin, test)] -#![cfg_attr(feature = "clippy", plugin(clippy))] -#![plugin(serde_macros)] - -extern crate rustc_serialize; -extern crate serde; -extern crate test; - -include!("../../testing/benches/bench.rs.in"); diff --git a/serde_macros/src/lib.rs b/serde_macros/src/lib.rs deleted file mode 100644 index 077fdccf..00000000 --- a/serde_macros/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![feature(plugin_registrar, rustc_private)] -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] - -extern crate serde_codegen; -extern crate rustc_plugin; - -#[plugin_registrar] -#[doc(hidden)] -pub fn plugin_registrar(reg: &mut rustc_plugin::Registry) { - serde_codegen::register(reg); -} diff --git a/serde_macros/tests/compile-fail/duplicate_attributes.rs b/serde_macros/tests/compile-fail/duplicate_attributes.rs deleted file mode 100644 index 61c98697..00000000 --- a/serde_macros/tests/compile-fail/duplicate_attributes.rs +++ /dev/null @@ -1,32 +0,0 @@ -#![feature(custom_attribute, custom_derive, plugin)] -#![plugin(serde_macros)] - -#[derive(Serialize)] //~ ERROR: 6 errors: -struct S { - #[serde(rename(serialize="x"))] - #[serde(rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` - a: (), - - #[serde(rename(serialize="x"))] - #[serde(rename="y")] // ERROR: duplicate serde attribute `rename` - b: (), - - #[serde(rename(serialize="x"))] - #[serde(rename(deserialize="y"))] // ok - c: (), - - #[serde(rename="x")] - #[serde(rename(deserialize="y"))] // ERROR: duplicate serde attribute `rename` - d: (), - - #[serde(rename(serialize="x", serialize="y"))] // ERROR: duplicate serde attribute `rename` - e: (), - - #[serde(rename="x", serialize="y")] // ERROR: unknown serde field attribute `serialize` - f: (), - - #[serde(rename(serialize="x"), rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` - g: (), -} - -fn main() {} diff --git a/serde_macros/tests/compile-fail/reject-unknown-attributes.rs b/serde_macros/tests/compile-fail/reject-unknown-attributes.rs deleted file mode 100644 index 3295b3ad..00000000 --- a/serde_macros/tests/compile-fail/reject-unknown-attributes.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![feature(custom_attribute, custom_derive, plugin)] -#![plugin(serde_macros)] - -extern crate serde; - -#[derive(Serialize)] //~ unknown serde container attribute `abc` -#[serde(abc="xyz")] -struct A { - x: u32, -} - -#[derive(Deserialize)] //~ unknown serde container attribute `abc` -#[serde(abc="xyz")] -struct B { - x: u32, -} - -#[derive(Serialize)] //~ unknown serde field attribute `abc` -struct C { - #[serde(abc="xyz")] - x: u32, -} - -#[derive(Deserialize)] //~ unknown serde field attribute `abc` -struct D { - #[serde(abc="xyz")] - x: u32, -} - -fn main() { } diff --git a/serde_macros/tests/compile-fail/str_ref_deser.rs b/serde_macros/tests/compile-fail/str_ref_deser.rs deleted file mode 100644 index 610ed680..00000000 --- a/serde_macros/tests/compile-fail/str_ref_deser.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(custom_attribute, custom_derive, plugin)] -#![plugin(serde_macros)] - -#[derive(Serialize, Deserialize)] //~ ERROR: Serde does not support deserializing fields of type &str -struct Test<'a> { - s: &'a str, -} - -fn main() {} diff --git a/serde_macros/tests/test.rs b/serde_macros/tests/test.rs deleted file mode 100644 index e0462787..00000000 --- a/serde_macros/tests/test.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(test, custom_attribute, custom_derive, plugin)] -#![plugin(serde_macros)] - -extern crate test; - -include!("../../testing/tests/test.rs.in"); - -mod compile_tests; From b27039d34d79058d3bbd33b2a33ad5e67db81372 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 28 Sep 2016 12:46:54 -0700 Subject: [PATCH 049/111] Compiletest error messages --- .../tests/compile-fail/duplicate-attribute/rename-and-ser.rs | 2 +- .../tests/compile-fail/duplicate-attribute/rename-rename-de.rs | 2 +- .../compile-fail/duplicate-attribute/rename-ser-rename-ser.rs | 2 +- .../tests/compile-fail/duplicate-attribute/rename-ser-rename.rs | 2 +- .../tests/compile-fail/duplicate-attribute/rename-ser-ser.rs | 2 +- .../tests/compile-fail/duplicate-attribute/two-rename-ser.rs | 2 +- serde_derive/tests/compile-fail/str_ref_deser.rs | 2 +- serde_derive/tests/compile-fail/unknown-attribute/container.rs | 2 +- serde_derive/tests/compile-fail/unknown-attribute/field.rs | 2 +- serde_derive/tests/compile-fail/unknown-attribute/variant.rs | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs index 4a6590aa..312583af 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs @@ -5,7 +5,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct S { - #[serde(rename="x", serialize="y")] // ERROR: unknown serde field attribute `serialize` + #[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize` x: (), } diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs index 21a31b6c..e6d6876a 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs @@ -6,7 +6,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct S { #[serde(rename="x")] - #[serde(rename(deserialize="y"))] // ERROR: duplicate serde attribute `rename` + #[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename` x: (), } diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs index be64ec03..d6937559 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs @@ -5,7 +5,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct S { - #[serde(rename(serialize="x"), rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` + #[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename` x: (), } diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs index 1dd2a982..dcb0f69e 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs @@ -6,7 +6,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct S { #[serde(rename(serialize="x"))] - #[serde(rename="y")] // ERROR: duplicate serde attribute `rename` + #[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename` x: (), } diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs index ef9a7c5c..af9116e5 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs @@ -5,7 +5,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct S { - #[serde(rename(serialize="x", serialize="y"))] // ERROR: duplicate serde attribute `rename` + #[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename` x: (), } diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs index 35e9a5a0..a518839d 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs @@ -6,7 +6,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct S { #[serde(rename(serialize="x"))] - #[serde(rename(serialize="y"))] // ERROR: duplicate serde attribute `rename` + #[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename` x: (), } diff --git a/serde_derive/tests/compile-fail/str_ref_deser.rs b/serde_derive/tests/compile-fail/str_ref_deser.rs index 98c21617..9a99e72b 100644 --- a/serde_derive/tests/compile-fail/str_ref_deser.rs +++ b/serde_derive/tests/compile-fail/str_ref_deser.rs @@ -5,7 +5,7 @@ extern crate serde_derive; #[derive(Serialize, Deserialize)] //~ ERROR: custom derive attribute panicked struct Test<'a> { - s: &'a str, // ERROR: Serde does not support deserializing fields of type &str + s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str } fn main() {} diff --git a/serde_derive/tests/compile-fail/unknown-attribute/container.rs b/serde_derive/tests/compile-fail/unknown-attribute/container.rs index 1815a7ce..2b0e1cb2 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/container.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/container.rs @@ -4,7 +4,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked -#[serde(abc="xyz")] // ERROR: unknown serde container attribute `abc` +#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc` struct A { x: u32, } diff --git a/serde_derive/tests/compile-fail/unknown-attribute/field.rs b/serde_derive/tests/compile-fail/unknown-attribute/field.rs index 5cc6372c..1b2d8e6c 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/field.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/field.rs @@ -5,7 +5,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked struct C { - #[serde(abc="xyz")] // ERROR: unknown serde field attribute `abc` + #[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc` x: u32, } diff --git a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs index 353ef91f..239fcc89 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs @@ -5,7 +5,7 @@ extern crate serde_derive; #[derive(Serialize)] //~ ERROR: custom derive attribute panicked enum E { - #[serde(abc="xyz")] // ERROR: unknown serde variant attribute `abc` + #[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc` V, } From 392099337045829e31b786f12083b71ad2ad7dfc Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 29 Sep 2016 15:46:07 +0200 Subject: [PATCH 050/111] Allow the use of `IpAddr` implementations on stable Also use the same strategy for serialization as for deserialization of `IpAddr`. Fixes #551. --- serde/src/de/impls.rs | 2 +- serde/src/ser/impls.rs | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 83a8f2c5..e7b9bb64 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -809,7 +809,7 @@ map_impl!( /////////////////////////////////////////////////////////////////////////////// -#[cfg(all(feature = "unstable", feature = "std"))] +#[cfg(feature = "std")] impl Deserialize for net::IpAddr { fn deserialize(deserializer: &mut D) -> Result where D: Deserializer, diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 348c8c77..58a1683e 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -640,15 +640,12 @@ impl Serialize for Duration { /////////////////////////////////////////////////////////////////////////////// -#[cfg(all(feature = "std", feature = "unstable"))] +#[cfg(feature = "std")] impl Serialize for net::IpAddr { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer, { - match *self { - net::IpAddr::V4(ref addr) => addr.serialize(serializer), - net::IpAddr::V6(ref addr) => addr.serialize(serializer), - } + self.to_string().serialize(serializer) } } From 3f28a9324042950afa80354722aeeee1a55cbfa3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 29 Sep 2016 09:21:01 -0700 Subject: [PATCH 051/111] Update readme to serde_derive --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a8839d5..448d9ed2 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,10 @@ You may be looking for: ## Serde in action ```rust -#![feature(plugin, custom_derive)] -#![plugin(serde_macros)] +#![feature(rustc_macro)] + +#[macro_use] +extern crate serde_derive; extern crate serde_json; From 42987a5b246af51a42b158665c63b4ec052e2b3c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Oct 2016 13:37:46 -0700 Subject: [PATCH 052/111] Fix break in quote 0.2.2 --- serde_codegen/src/de.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index ec2f9026..4e74b5fa 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -651,14 +651,6 @@ fn deserialize_field_visitor( Some(quote!(__ignore,)) }; - let field_enum = quote! { - #[allow(non_camel_case_types)] - enum __Field { - #(field_idents,)* - #ignore_variant - } - }; - let index_field_arms: Vec<_> = field_idents.iter() .enumerate() .map(|(field_index, field_ident)| { @@ -745,6 +737,14 @@ fn deserialize_field_visitor( } }; + let field_enum = quote! { + #[allow(non_camel_case_types)] + enum __Field { + #(field_idents,)* + #ignore_variant + } + }; + let impl_item = quote! { impl _serde::de::Deserialize for __Field { #[inline] From c61b20cceb579d7b59408b2fca131ac3b5425732 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Oct 2016 13:38:52 -0700 Subject: [PATCH 053/111] Release 0.8.11 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index f3db9bc7..7b951894 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.10" +version = "0.8.11" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index a4ed927c..5dafe866 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.10" +version = "0.8.11" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 32960964..6ee9949d 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.10" +version = "0.8.11" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" rustc-macro = true [dependencies.serde_codegen] -version = "=0.8.10" +version = "=0.8.11" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.10", path = "../serde" } -serde_test = { version = "0.8.10", path = "../serde_test" } +serde = { version = "0.8.11", path = "../serde" } +serde_test = { version = "0.8.11", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index aa7eb3a1..5b114e4a 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.10" +version = "0.8.11" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.10", path = "../serde" } +serde = { version = "0.8.11", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 9110b079..b359e2a4 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.10" +version = "0.8.11" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From e547a06639ee62dff40813afbbdbf1ed1d792e99 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Oct 2016 13:45:11 -0700 Subject: [PATCH 054/111] Simplify deserialize_field_visitor --- serde_codegen/src/de.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 4e74b5fa..db266458 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -737,15 +737,13 @@ fn deserialize_field_visitor( } }; - let field_enum = quote! { + quote! { #[allow(non_camel_case_types)] enum __Field { #(field_idents,)* #ignore_variant } - }; - let impl_item = quote! { impl _serde::de::Deserialize for __Field { #[inline] fn deserialize<__D>(deserializer: &mut __D) -> ::std::result::Result<__Field, __D::Error> @@ -778,11 +776,6 @@ fn deserialize_field_visitor( deserializer.deserialize_struct_field(__FieldVisitor) } } - }; - - quote! { - #field_enum - #impl_item } } From ef5d09e14446e9a96d614be4d3973c4b36b35b45 Mon Sep 17 00:00:00 2001 From: Mark Roghelia Date: Sat, 8 Oct 2016 18:29:36 -0400 Subject: [PATCH 055/111] Rename rustc_macro to proc_macro Fixes #575 --- README.md | 2 +- examples/serde-syntex-example/src/main.rs | 2 +- serde_derive/Cargo.toml | 2 +- serde_derive/src/lib.rs | 10 +++++----- .../compile-fail/duplicate-attribute/rename-and-ser.rs | 2 +- .../duplicate-attribute/rename-rename-de.rs | 2 +- .../duplicate-attribute/rename-ser-rename-ser.rs | 2 +- .../duplicate-attribute/rename-ser-rename.rs | 2 +- .../compile-fail/duplicate-attribute/rename-ser-ser.rs | 2 +- .../compile-fail/duplicate-attribute/two-rename-ser.rs | 2 +- serde_derive/tests/compile-fail/str_ref_deser.rs | 2 +- .../tests/compile-fail/unknown-attribute/container.rs | 2 +- .../tests/compile-fail/unknown-attribute/field.rs | 2 +- .../tests/compile-fail/unknown-attribute/variant.rs | 2 +- serde_derive/tests/run-pass/identity-op.rs | 2 +- serde_derive/tests/test.rs | 2 +- 16 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 448d9ed2..f0c6ec64 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ You may be looking for: ## Serde in action ```rust -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/examples/serde-syntex-example/src/main.rs b/examples/serde-syntex-example/src/main.rs index 46e7d1dc..1d6e2058 100644 --- a/examples/serde-syntex-example/src/main.rs +++ b/examples/serde-syntex-example/src/main.rs @@ -1,4 +1,4 @@ -#![cfg_attr(feature = "serde_derive", feature(rustc_macro))] +#![cfg_attr(feature = "serde_derive", feature(proc_macro))] #[cfg(feature = "serde_derive")] #[macro_use] diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 6ee9949d..a8288a22 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -12,7 +12,7 @@ include = ["Cargo.toml", "src/**/*.rs"] [lib] name = "serde_derive" -rustc-macro = true +proc-macro = true [dependencies.serde_codegen] version = "=0.8.11" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 0f435142..8dd4e6ff 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,12 +1,12 @@ -#![feature(rustc_macro, rustc_macro_lib)] +#![feature(proc_macro, proc_macro_lib)] #![cfg(not(test))] -extern crate rustc_macro; +extern crate proc_macro; extern crate serde_codegen; -use rustc_macro::TokenStream; +use proc_macro::TokenStream; -#[rustc_macro_derive(Serialize)] +#[proc_macro_derive(Serialize)] pub fn derive_serialize(input: TokenStream) -> TokenStream { let item = format!("#[derive(Serialize)]\n{}", input); match serde_codegen::expand_single_item(&item) { @@ -15,7 +15,7 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream { } } -#[rustc_macro_derive(Deserialize)] +#[proc_macro_derive(Deserialize)] pub fn derive_deserialize(input: TokenStream) -> TokenStream { let item = format!("#[derive(Deserialize)]\n{}", input); match serde_codegen::expand_single_item(&item) { diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs index 312583af..2f3950f8 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs index e6d6876a..04718a0e 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs index d6937559..420182c4 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs index dcb0f69e..52715b9d 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs index af9116e5..31264c6b 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs index a518839d..d6054529 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/str_ref_deser.rs b/serde_derive/tests/compile-fail/str_ref_deser.rs index 9a99e72b..58ae577c 100644 --- a/serde_derive/tests/compile-fail/str_ref_deser.rs +++ b/serde_derive/tests/compile-fail/str_ref_deser.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/unknown-attribute/container.rs b/serde_derive/tests/compile-fail/unknown-attribute/container.rs index 2b0e1cb2..575cc10c 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/container.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/container.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/unknown-attribute/field.rs b/serde_derive/tests/compile-fail/unknown-attribute/field.rs index 1b2d8e6c..457ce520 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/field.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/field.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs index 239fcc89..af5c323a 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/run-pass/identity-op.rs b/serde_derive/tests/run-pass/identity-op.rs index 47e2c750..0def143e 100644 --- a/serde_derive/tests/run-pass/identity-op.rs +++ b/serde_derive/tests/run-pass/identity-op.rs @@ -1,4 +1,4 @@ -#![feature(rustc_macro)] +#![feature(proc_macro)] #![deny(identity_op)] #[macro_use] diff --git a/serde_derive/tests/test.rs b/serde_derive/tests/test.rs index 80239edf..696a4bc4 100644 --- a/serde_derive/tests/test.rs +++ b/serde_derive/tests/test.rs @@ -1,4 +1,4 @@ -#![feature(test, rustc_macro, rustc_attrs)] +#![feature(test, proc_macro, rustc_attrs)] #[macro_use] extern crate serde_derive; From b4d5c26f4eaa0f21a6d82a3a58ffb3f2688c7736 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 3 Oct 2016 21:09:52 -0700 Subject: [PATCH 056/111] Update to latest syn and quote --- serde_codegen/Cargo.toml | 4 ++-- serde_codegen/src/de.rs | 38 +++++++++++++++--------------- serde_codegen/src/lib.rs | 4 +++- serde_codegen/src/ser.rs | 14 +++++------ serde_codegen_internals/Cargo.toml | 2 +- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 5dafe866..cefc2e01 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,8 +22,8 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } -quote = "0.2" +quote = "0.3" serde_codegen_internals = { version = "=0.9.0", default-features = false, path = "../serde_codegen_internals" } -syn = { version = "0.8", features = ["aster", "visit"] } +syn = { version = "0.9", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index db266458..173b68f6 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -185,17 +185,17 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) { let ty_param_idents = if ty_param_idents.is_empty() { None } else { - Some(quote!(::<#(ty_param_idents),*>)) + Some(quote!(::<#(#ty_param_idents),*>)) }; let phantom_exprs = iter::repeat(quote!(::std::marker::PhantomData)).take(num_phantoms); ( quote! { - struct __Visitor #generics ( #(phantom_types),* ) #where_clause; + struct __Visitor #generics ( #(#phantom_types),* ) #where_clause; }, - quote!(__Visitor <#(all_params),*> ), - quote!(__Visitor #ty_param_idents ( #(phantom_exprs),* )), + quote!(__Visitor <#(#all_params),*> ), + quote!(__Visitor #ty_param_idents ( #(#phantom_exprs),* )), ) } } @@ -358,17 +358,17 @@ fn deserialize_seq( quote!(#ident: #value) }); quote! { - #type_path { #(args),* } + #type_path { #(#args),* } } } else { let args = (0..fields.len()).map(|i| aster::id(format!("__field{}", i))); quote! { - #type_path ( #(args),* ) + #type_path ( #(#args),* ) } }; quote! { - #(let_values)* + #(#let_values)* try!(visitor.end()); @@ -505,7 +505,7 @@ fn deserialize_item_enum( let variant_names = variants.iter().map(|variant| variant.ident.to_string()); let variants_stmt = quote! { - const VARIANTS: &'static [&'static str] = &[ #(variant_names),* ]; + const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; }; let ignored_arm = if item_attrs.deny_unknown_fields() { @@ -551,7 +551,7 @@ fn deserialize_item_enum( where __V: _serde::de::VariantVisitor, { match try!(visitor.visit_variant()) { - #(variant_arms)* + #(#variant_arms)* } } } @@ -678,7 +678,7 @@ fn deserialize_field_visitor( let index_body = quote! { match value { - #(index_field_arms)* + #(#index_field_arms)* _ => #fallthrough_index_arm_expr } }; @@ -704,7 +704,7 @@ fn deserialize_field_visitor( let str_body = quote! { match value { - #(str_field_arms)* + #(#str_field_arms)* _ => #fallthrough_str_arm_expr } }; @@ -732,7 +732,7 @@ fn deserialize_field_visitor( let bytes_body = quote! { match value { - #(bytes_field_arms)* + #(#bytes_field_arms)* _ => #fallthrough_bytes_arm_expr } }; @@ -740,7 +740,7 @@ fn deserialize_field_visitor( quote! { #[allow(non_camel_case_types)] enum __Field { - #(field_idents,)* + #(#field_idents,)* #ignore_variant } @@ -809,7 +809,7 @@ fn deserialize_struct_visitor( }); let fields_stmt = quote! { - const FIELDS: &'static [&'static str] = &[ #(field_names),* ]; + const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; }; (field_visitor, fields_stmt, visit_map) @@ -922,21 +922,21 @@ fn deserialize_map( }); quote! { - #(let_values)* + #(#let_values)* while let Some(key) = try!(visitor.visit_key::<__Field>()) { match key { - #(value_arms)* - #(skipped_arms)* + #(#value_arms)* + #(#skipped_arms)* #ignored_arm } } try!(visitor.end()); - #(extract_values)* + #(#extract_values)* - Ok(#struct_path { #(result),* }) + Ok(#struct_path { #(#result),* }) } } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 9656016d..42e3a0c7 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -201,7 +201,7 @@ pub fn expand_single_item(item: &str) -> Result { let mut de = false; let item = syn::MacroInput { attrs: item.attrs.into_iter().flat_map(|attr| { - if attr.is_sugared_doc { + if attr.is_sugared_doc || attr.style != syn::AttrStyle::Outer { return Some(attr); } let (name, nested) = match attr.value { @@ -210,6 +210,7 @@ pub fn expand_single_item(item: &str) -> Result { }; if name != "derive" { return Some(syn::Attribute { + style: syn::AttrStyle::Outer, value: syn::MetaItem::List(name, nested), is_sugared_doc: false, }); @@ -231,6 +232,7 @@ pub fn expand_single_item(item: &str) -> Result { None } else { Some(syn::Attribute { + style: syn::AttrStyle::Outer, value: syn::MetaItem::List(name, rest), is_sugared_doc: false, }) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 0bbcd7e9..449a2490 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -168,7 +168,7 @@ fn serialize_tuple_struct( quote! { let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len)); - #(serialize_stmts)* + #(#serialize_stmts)* _serializer.serialize_tuple_struct_end(__serde_state) } } @@ -209,7 +209,7 @@ fn serialize_struct( quote! { let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len)); - #(serialize_fields)* + #(#serialize_fields)* _serializer.serialize_struct_end(__serde_state) } } @@ -238,7 +238,7 @@ fn serialize_item_enum( quote! { match *self { - #(arms)* + #(#arms)* } } } @@ -290,7 +290,7 @@ fn serialize_variant( }) .collect(); - let pat = quote!(#type_ident::#variant_ident(#(field_names),*)); + let pat = quote!(#type_ident::#variant_ident(#(#field_names),*)); let block = serialize_tuple_variant( type_name, @@ -313,7 +313,7 @@ fn serialize_variant( }; quote!(ref #id) }); - let pat = quote!(#type_ident::#variant_ident { #(fields),* }); + let pat = quote!(#type_ident::#variant_ident { #(#fields),* }); let block = serialize_struct_variant( variant_index, @@ -381,7 +381,7 @@ fn serialize_tuple_variant( #variant_index, #variant_name, #len)); - #(serialize_stmts)* + #(#serialize_stmts)* _serializer.serialize_tuple_variant_end(__serde_state) } } @@ -428,7 +428,7 @@ fn serialize_struct_variant( #variant_name, #len, )); - #(serialize_fields)* + #(#serialize_fields)* _serializer.serialize_struct_variant_end(__serde_state) } } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 5213aeaf..fc4788ac 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -15,4 +15,4 @@ unstable-testing = ["clippy"] [dependencies] clippy = { version = "^0.*", optional = true } -syn = "0.8" +syn = "0.9" From 339c0f54937e2091f676840240cf477a615f0f1c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 8 Oct 2016 15:36:46 -0700 Subject: [PATCH 057/111] Remove unneeded test feature --- serde_derive/tests/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/tests/test.rs b/serde_derive/tests/test.rs index 696a4bc4..fde3cfa2 100644 --- a/serde_derive/tests/test.rs +++ b/serde_derive/tests/test.rs @@ -1,4 +1,4 @@ -#![feature(test, proc_macro, rustc_attrs)] +#![feature(test, proc_macro)] #[macro_use] extern crate serde_derive; From 85c95040b31bccb39ff05df9c4f6ead66c44414b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 8 Oct 2016 15:38:29 -0700 Subject: [PATCH 058/111] Release 0.8.12 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 4 ++-- serde_codegen_internals/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 7b951894..5246e29d 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.11" +version = "0.8.12" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index cefc2e01..d1a00f0c 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.11" +version = "0.8.12" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,7 +23,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } quote = "0.3" -serde_codegen_internals = { version = "=0.9.0", default-features = false, path = "../serde_codegen_internals" } +serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.9", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index fc4788ac..37065da6 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.9.0" +version = "0.10.0" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index a8288a22..e8f11f74 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.11" +version = "0.8.12" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.11" +version = "=0.8.12" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.11", path = "../serde" } -serde_test = { version = "0.8.11", path = "../serde_test" } +serde = { version = "0.8.12", path = "../serde" } +serde_test = { version = "0.8.12", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 5b114e4a..6f5378cd 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.11" +version = "0.8.12" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.11", path = "../serde" } +serde = { version = "0.8.12", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index b359e2a4..4ac23c82 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.11" +version = "0.8.12" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 99bddddd8eb86caeda809e83cf493e7c20ef9d5f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 14 Oct 2016 00:15:24 -0700 Subject: [PATCH 059/111] Array and tuple deserialization cleanup --- serde/src/de/impls.rs | 167 +++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 98 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index e7b9bb64..915ef5b2 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -512,27 +512,26 @@ seq_impl!( /////////////////////////////////////////////////////////////////////////////// -struct ArrayVisitor0 { - marker: PhantomData, +struct ArrayVisitor { + marker: PhantomData, } -impl ArrayVisitor0 { - /// Construct a `ArrayVisitor0`. +impl ArrayVisitor { pub fn new() -> Self { - ArrayVisitor0 { + ArrayVisitor { marker: PhantomData, } } } -impl Visitor for ArrayVisitor0 where T: Deserialize + Default { +impl Visitor for ArrayVisitor<[T; 0]> where T: Deserialize { type Value = [T; 0]; #[inline] fn visit_unit(&mut self) -> Result<[T; 0], E> where E: Error, { - Ok([T::default(); 0]) + Ok([]) } #[inline] @@ -540,37 +539,24 @@ impl Visitor for ArrayVisitor0 where T: Deserialize + Default { where V: SeqVisitor, { try!(visitor.end()); - Ok([T::default(); 0]) + Ok([]) } } impl Deserialize for [T; 0] - where T: Deserialize + Default + where T: Deserialize { fn deserialize(deserializer: &mut D) -> Result<[T; 0], D::Error> where D: Deserializer, { - deserializer.deserialize_seq(ArrayVisitor0::new()) + deserializer.deserialize_seq_fixed_size(0, ArrayVisitor::<[T; 0]>::new()) } } macro_rules! array_impls { - ($($visitor:ident, $len:expr => ($($name:ident),+),)+) => { + ($($len:expr => ($($name:ident)+))+) => { $( - struct $visitor { - marker: PhantomData, - } - - impl $visitor { - /// Construct a `ArrayVisitor*`. - pub fn new() -> Self { - $visitor { - marker: PhantomData - } - } - } - - impl Visitor for $visitor where T: Deserialize { + impl Visitor for ArrayVisitor<[T; $len]> where T: Deserialize { type Value = [T; $len]; #[inline] @@ -580,13 +566,13 @@ macro_rules! array_impls { $( let $name = match try!(visitor.visit()) { Some(val) => val, - None => { return Err(Error::end_of_stream()); } + None => return Err(Error::end_of_stream()), }; - )+; + )+ try!(visitor.end()); - Ok([$($name,)+]) + Ok([$($name),+]) } } @@ -596,7 +582,7 @@ macro_rules! array_impls { fn deserialize(deserializer: &mut D) -> Result<[T; $len], D::Error> where D: Deserializer, { - deserializer.deserialize_seq_fixed_size($len, $visitor::new()) + deserializer.deserialize_seq_fixed_size($len, ArrayVisitor::<[T; $len]>::new()) } } )+ @@ -604,71 +590,58 @@ macro_rules! array_impls { } array_impls! { - ArrayVisitor1, 1 => (a), - ArrayVisitor2, 2 => (a, b), - ArrayVisitor3, 3 => (a, b, c), - ArrayVisitor4, 4 => (a, b, c, d), - ArrayVisitor5, 5 => (a, b, c, d, e), - ArrayVisitor6, 6 => (a, b, c, d, e, f), - ArrayVisitor7, 7 => (a, b, c, d, e, f, g), - ArrayVisitor8, 8 => (a, b, c, d, e, f, g, h), - ArrayVisitor9, 9 => (a, b, c, d, e, f, g, h, i), - ArrayVisitor10, 10 => (a, b, c, d, e, f, g, h, i, j), - ArrayVisitor11, 11 => (a, b, c, d, e, f, g, h, i, j, k), - ArrayVisitor12, 12 => (a, b, c, d, e, f, g, h, i, j, k, l), - ArrayVisitor13, 13 => (a, b, c, d, e, f, g, h, i, j, k, l, m), - ArrayVisitor14, 14 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n), - ArrayVisitor15, 15 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o), - ArrayVisitor16, 16 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p), - ArrayVisitor17, 17 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q), - ArrayVisitor18, 18 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r), - ArrayVisitor19, 19 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s), - ArrayVisitor20, 20 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ,t), - ArrayVisitor21, 21 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u), - ArrayVisitor22, 22 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v), - ArrayVisitor23, 23 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w), - ArrayVisitor24, 24 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x), - ArrayVisitor25, 25 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y), - ArrayVisitor26, 26 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z), - ArrayVisitor27, 27 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z, aa), - ArrayVisitor28, 28 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z, aa, ab), - ArrayVisitor29, 29 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z, aa, ab, ac), - ArrayVisitor30, 30 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z, aa, ab, ac, ad), - ArrayVisitor31, 31 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z, aa, ab, ac, ad, ae), - ArrayVisitor32, 32 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, - y, z, aa, ab, ac, ad, ae, af), + 1 => (a) + 2 => (a b) + 3 => (a b c) + 4 => (a b c d) + 5 => (a b c d e) + 6 => (a b c d e f) + 7 => (a b c d e f g) + 8 => (a b c d e f g h) + 9 => (a b c d e f g h i) + 10 => (a b c d e f g h i j) + 11 => (a b c d e f g h i j k) + 12 => (a b c d e f g h i j k l) + 13 => (a b c d e f g h i j k l m) + 14 => (a b c d e f g h i j k l m n) + 15 => (a b c d e f g h i j k l m n o) + 16 => (a b c d e f g h i j k l m n o p) + 17 => (a b c d e f g h i j k l m n o p q) + 18 => (a b c d e f g h i j k l m n o p q r) + 19 => (a b c d e f g h i j k l m n o p q r s) + 20 => (a b c d e f g h i j k l m n o p q r s t) + 21 => (a b c d e f g h i j k l m n o p q r s t u) + 22 => (a b c d e f g h i j k l m n o p q r s t u v) + 23 => (a b c d e f g h i j k l m n o p q r s t u v w) + 24 => (a b c d e f g h i j k l m n o p q r s t u v w x) + 25 => (a b c d e f g h i j k l m n o p q r s t u v w x y) + 26 => (a b c d e f g h i j k l m n o p q r s t u v w x y z) + 27 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa) + 28 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab) + 29 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac) + 30 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad) + 31 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae) + 32 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af) } /////////////////////////////////////////////////////////////////////////////// macro_rules! tuple_impls { - ($($len:expr => $visitor:ident => ($($name:ident),+),)+) => { + ($($len:expr => $visitor:ident => ($($name:ident)+))+) => { $( /// Construct a tuple visitor. pub struct $visitor<$($name,)+> { marker: PhantomData<($($name,)+)>, } - impl< - $($name: Deserialize,)+ - > $visitor<$($name,)+> { + impl<$($name: Deserialize,)+> $visitor<$($name,)+> { /// Construct a `TupleVisitor*`. pub fn new() -> Self { $visitor { marker: PhantomData } } } - - impl< - $($name: Deserialize,)+ - > Visitor for $visitor<$($name,)+> { + impl<$($name: Deserialize),+> Visitor for $visitor<$($name,)+> { type Value = ($($name,)+); #[inline] @@ -679,9 +652,9 @@ macro_rules! tuple_impls { $( let $name = match try!(visitor.visit()) { Some(value) => value, - None => { return Err(Error::end_of_stream()); } + None => return Err(Error::end_of_stream()), }; - )+; + )+ try!(visitor.end()); @@ -689,9 +662,7 @@ macro_rules! tuple_impls { } } - impl< - $($name: Deserialize),+ - > Deserialize for ($($name,)+) { + impl<$($name: Deserialize),+> Deserialize for ($($name,)+) { #[inline] fn deserialize(deserializer: &mut D) -> Result<($($name,)+), D::Error> where D: Deserializer, @@ -704,22 +675,22 @@ macro_rules! tuple_impls { } tuple_impls! { - 1 => TupleVisitor1 => (T0), - 2 => TupleVisitor2 => (T0, T1), - 3 => TupleVisitor3 => (T0, T1, T2), - 4 => TupleVisitor4 => (T0, T1, T2, T3), - 5 => TupleVisitor5 => (T0, T1, T2, T3, T4), - 6 => TupleVisitor6 => (T0, T1, T2, T3, T4, T5), - 7 => TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6), - 8 => TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7), - 9 => TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8), - 10 => TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), - 11 => TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), - 12 => TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), - 13 => TupleVisitor13 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), - 14 => TupleVisitor14 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), - 15 => TupleVisitor15 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), - 16 => TupleVisitor16 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), + 1 => TupleVisitor1 => (T0) + 2 => TupleVisitor2 => (T0 T1) + 3 => TupleVisitor3 => (T0 T1 T2) + 4 => TupleVisitor4 => (T0 T1 T2 T3) + 5 => TupleVisitor5 => (T0 T1 T2 T3 T4) + 6 => TupleVisitor6 => (T0 T1 T2 T3 T4 T5) + 7 => TupleVisitor7 => (T0 T1 T2 T3 T4 T5 T6) + 8 => TupleVisitor8 => (T0 T1 T2 T3 T4 T5 T6 T7) + 9 => TupleVisitor9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8) + 10 => TupleVisitor10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9) + 11 => TupleVisitor11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10) + 12 => TupleVisitor12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11) + 13 => TupleVisitor13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12) + 14 => TupleVisitor14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13) + 15 => TupleVisitor15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14) + 16 => TupleVisitor16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15) } /////////////////////////////////////////////////////////////////////////////// From 4919a3184d7babff03dad99116b0478be62fb43b Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 15 Oct 2016 14:01:14 -0700 Subject: [PATCH 060/111] Update syntex version to 0.45.0 --- serde_codegen/Cargo.toml | 6 +++--- serde_derive/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index d1a00f0c..9df0192c 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.12" +version = "0.8.13" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -25,5 +25,5 @@ clippy = { version = "^0.*", optional = true } quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.9", features = ["aster", "visit"] } -syntex = { version = "^0.44.0", optional = true } -syntex_syntax = { version = "^0.44.0", optional = true } +syntex = { version = "^0.45.0", optional = true } +syntex_syntax = { version = "^0.45.0", optional = true } diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index e8f11f74..a18ea366 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.12" +version = "=0.8.13" path = "../serde_codegen" default-features = false features = ["with-syn"] From cbe6b4c97c069f09acf7e8687ae47bf762791268 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 15 Oct 2016 14:03:42 -0700 Subject: [PATCH 061/111] Drop support for rust 1.8.0 and 1.9.0. --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 825b6a07..1a2e08d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,11 @@ sudo: false language: rust rust: +- 1.10.0 +- 1.11.0 - stable -- nightly -- 1.8.0 -- 1.9.0 - beta +- nightly addons: apt: packages: From f93b4e91e673da7946b6693e068523239d6dccce Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 15 Oct 2016 15:24:37 -0700 Subject: [PATCH 062/111] Version bump serde_derive to 0.8.13 --- serde_derive/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index a18ea366..36f28dd4 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.12" +version = "0.8.13" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" From 532b95097194c19d4cc76c6d84655a0f56d905a5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Oct 2016 10:34:26 -0700 Subject: [PATCH 063/111] Release 0.8.13 --- serde/Cargo.toml | 2 +- serde_derive/Cargo.toml | 4 ++-- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 5246e29d..be52d384 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.12" +version = "0.8.13" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 36f28dd4..187755b6 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.12", path = "../serde" } -serde_test = { version = "0.8.12", path = "../serde_test" } +serde = { version = "0.8.13", path = "../serde" } +serde_test = { version = "0.8.13", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 6f5378cd..63ae9b53 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.12" +version = "0.8.13" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.12", path = "../serde" } +serde = { version = "0.8.13", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 4ac23c82..c44975b6 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.12" +version = "0.8.13" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 1d719b542cb8d5471633f5a9839f7fd22f3cde3e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 17 Oct 2016 23:12:29 -0700 Subject: [PATCH 064/111] Not safe to share Spans from one ParseSess to another Spans in the AST returned by `parse_item_from_source_str` and other parsing functions contain byte offsets into the source code they were parsed from. The pretty printer uses these Spans [here][1] to preserve the representation of literals when parsing and printing back out unmodified. In this bug, the byte offset of a string in the input to `parse_item_from_source_str` coincidentally matched the byte offset of a totally different string in the input to `parse_crate_from_file` called [here][2] by Syntex. The Span from the former triggered the pretty printer to write out the content of the latter. By using the same ParseSess, Spans from the two `parse_*` calls never collide. [1]: https://github.com/rust-lang/rust/blob/1.12.0/src/libsyntax/print/pprust.rs#L628 [2]: https://github.com/serde-rs/syntex/blob/v0.45.0/syntex/src/registry.rs#L134 --- serde_codegen/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 42e3a0c7..25a9fe03 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -169,8 +169,8 @@ macro_rules! shim { use syntax::parse; let name = stringify!($name).to_string(); let cfg = Vec::new(); - let sess = parse::ParseSess::new(); - let impl_item = parse::parse_item_from_source_str(name, expanded, cfg, &sess); + let sess = cx.parse_sess; + let impl_item = parse::parse_item_from_source_str(name, expanded, cfg, sess); push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap())); } }; From a9b6cbb8b37f64ae0f42a0013123ff49a174504e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 16 Oct 2016 23:17:17 -0700 Subject: [PATCH 065/111] Use post-expansion crate to let other custom derives see serde attrs --- serde_codegen/Cargo.toml | 1 + serde_codegen/src/lib.rs | 55 +++------------------------------------- serde_derive/Cargo.toml | 3 +++ serde_derive/src/lib.rs | 5 ++++ 4 files changed, 13 insertions(+), 51 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 9df0192c..85718720 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,6 +22,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } +post-expansion = "0.0.2" quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.9", features = ["aster", "visit"] } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 42e3a0c7..2b2bca94 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -27,6 +27,9 @@ extern crate syn; #[macro_use] extern crate quote; +#[cfg(feature = "with-syn")] +extern crate post_expansion; + #[cfg(feature = "with-syntex")] use std::path::Path; @@ -193,7 +196,7 @@ pub fn expand_single_item(item: &str) -> Result { } else { None:: }; - let syn_item = strip_serde_attrs(syn_item); + let syn_item = post_expansion::strip_attrs_later(syn_item, &["serde"], "serde"); return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string()); fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) { @@ -242,54 +245,4 @@ pub fn expand_single_item(item: &str) -> Result { }; (ser, de, item) } - - fn strip_serde_attrs(item: syn::MacroInput) -> syn::MacroInput { - syn::MacroInput { - attrs: strip_serde_from_attrs(item.attrs), - body: match item.body { - syn::Body::Enum(variants) => syn::Body::Enum( - variants.into_iter().map(|variant| { - syn::Variant { - ident: variant.ident, - attrs: strip_serde_from_attrs(variant.attrs), - data: strip_serde_from_variant_data(variant.data), - discriminant: variant.discriminant, - } - }).collect() - ), - syn::Body::Struct(variant_data) => syn::Body::Struct( - strip_serde_from_variant_data(variant_data) - ), - }, - ..item - } - } - - fn strip_serde_from_variant_data(data: syn::VariantData) -> syn::VariantData { - match data { - syn::VariantData::Struct(fields) => syn::VariantData::Struct( - fields.into_iter().map(strip_serde_from_field).collect() - ), - syn::VariantData::Tuple(fields) => syn::VariantData::Tuple( - fields.into_iter().map(strip_serde_from_field).collect() - ), - syn::VariantData::Unit => syn::VariantData::Unit, - } - } - - fn strip_serde_from_field(field: syn::Field) -> syn::Field { - syn::Field { - attrs: strip_serde_from_attrs(field.attrs), - ..field - } - } - - fn strip_serde_from_attrs(attrs: Vec) -> Vec { - attrs.into_iter().filter(|attr| { - match attr.value { - syn::MetaItem::List(ref ident, _) => ident != "serde", - _ => true, - } - }).collect() - } } diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 187755b6..29f9b4d5 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -14,6 +14,9 @@ include = ["Cargo.toml", "src/**/*.rs"] name = "serde_derive" proc-macro = true +[dependencies] +post-expansion = "0.0.2" + [dependencies.serde_codegen] version = "=0.8.13" path = "../serde_codegen" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index 8dd4e6ff..f631d6dd 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -4,6 +4,9 @@ extern crate proc_macro; extern crate serde_codegen; +#[macro_use] +extern crate post_expansion; + use proc_macro::TokenStream; #[proc_macro_derive(Serialize)] @@ -23,3 +26,5 @@ pub fn derive_deserialize(input: TokenStream) -> TokenStream { Err(msg) => panic!(msg), } } + +register_post_expansion!(PostExpansion_serde); From 1b42f3f594da4a8ad69051b4a3b5cbf08e2a2dfa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 18 Oct 2016 21:42:39 -0700 Subject: [PATCH 066/111] Release 0.8.14 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index be52d384..27ea433c 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.13" +version = "0.8.14" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 9df0192c..fdf61d22 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.13" +version = "0.8.14" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 187755b6..ef27dbb1 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.13" +version = "0.8.14" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.13" +version = "=0.8.14" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.13", path = "../serde" } -serde_test = { version = "0.8.13", path = "../serde_test" } +serde = { version = "0.8.14", path = "../serde" } +serde_test = { version = "0.8.14", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 63ae9b53..558569d9 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.13" +version = "0.8.14" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.13", path = "../serde" } +serde = { version = "0.8.14", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index c44975b6..fb7c04e9 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.13" +version = "0.8.14" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 21c94468908c00c891a9af8da0f9745312433725 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 18 Oct 2016 22:15:54 -0700 Subject: [PATCH 067/111] Update benchmarks to serde 0.8 --- testing/benches/bench.rs | 1 + testing/benches/bench_enum.rs | 42 ++++++++++++++++++++++++++++++++- testing/benches/bench_map.rs | 7 ++++++ testing/benches/bench_struct.rs | 6 +++++ testing/benches/bench_vec.rs | 14 +++++++++++ 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/testing/benches/bench.rs b/testing/benches/bench.rs index e5b10c57..80ebadac 100644 --- a/testing/benches/bench.rs +++ b/testing/benches/bench.rs @@ -3,6 +3,7 @@ #![cfg_attr(feature = "clippy", plugin(clippy))] extern crate rustc_serialize; +#[macro_use] extern crate serde; extern crate test; diff --git a/testing/benches/bench_enum.rs b/testing/benches/bench_enum.rs index 8badbb49..0e591c5b 100644 --- a/testing/benches/bench_enum.rs +++ b/testing/benches/bench_enum.rs @@ -251,7 +251,7 @@ mod decoder { mod deserializer { use super::{Animal, Error}; - use serde::de; + use serde::de::{self, Deserialize}; #[derive(Debug)] enum State { @@ -336,6 +336,12 @@ mod deserializer { } } } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit option seq seq_fixed_size bytes map unit_struct + newtype_struct tuple_struct struct struct_field tuple ignored_any + } } struct DogVisitor<'a> { @@ -354,6 +360,24 @@ mod deserializer { fn visit_unit(&mut self) -> Result<(), Error> { de::Deserialize::deserialize(self.de) } + + fn visit_newtype(&mut self) -> Result + where T: Deserialize + { + Err(de::Error::invalid_type(de::Type::TupleVariant)) + } + + fn visit_tuple(&mut self, _len: usize, _visitor: V) -> Result + where V: de::Visitor + { + Err(de::Error::invalid_type(de::Type::TupleVariant)) + } + + fn visit_struct(&mut self, _fields: &'static [&'static str], _visitor: V) -> Result + where V: de::Visitor + { + Err(de::Error::invalid_type(de::Type::StructVariant)) + } } struct FrogVisitor<'a> { @@ -377,6 +401,22 @@ mod deserializer { { visitor.visit_seq(self) } + + fn visit_unit(&mut self) -> Result<(), Error> { + Err(de::Error::invalid_type(de::Type::UnitVariant)) + } + + fn visit_newtype(&mut self) -> Result + where T: Deserialize + { + Err(de::Error::invalid_type(de::Type::TupleVariant)) + } + + fn visit_struct(&mut self, _fields: &'static [&'static str], _visitor: V) -> Result + where V: de::Visitor + { + Err(de::Error::invalid_type(de::Type::StructVariant)) + } } impl<'a> de::SeqVisitor for FrogVisitor<'a> { diff --git a/testing/benches/bench_map.rs b/testing/benches/bench_map.rs index 32bc4415..bd2bb70f 100644 --- a/testing/benches/bench_map.rs +++ b/testing/benches/bench_map.rs @@ -286,6 +286,13 @@ mod deserializer { } } } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit option seq seq_fixed_size bytes map unit_struct + newtype_struct tuple_struct struct struct_field tuple enum + ignored_any + } } impl de::MapVisitor for IsizeDeserializer { diff --git a/testing/benches/bench_struct.rs b/testing/benches/bench_struct.rs index 82b189e1..305de666 100644 --- a/testing/benches/bench_struct.rs +++ b/testing/benches/bench_struct.rs @@ -447,6 +447,12 @@ mod deserializer { } } } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit option seq seq_fixed_size bytes map unit_struct + newtype_struct tuple_struct struct_field tuple enum ignored_any + } } struct OuterMapVisitor<'a> { diff --git a/testing/benches/bench_vec.rs b/testing/benches/bench_vec.rs index 96a4e637..eb71fae9 100644 --- a/testing/benches/bench_vec.rs +++ b/testing/benches/bench_vec.rs @@ -411,6 +411,13 @@ mod deserializer { } } } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit option seq seq_fixed_size bytes map unit_struct + newtype_struct tuple_struct struct struct_field tuple enum + ignored_any + } } impl de::SeqVisitor for Deserializer { @@ -470,6 +477,13 @@ mod deserializer { } } } + + forward_to_deserialize! { + bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str + string unit option seq seq_fixed_size bytes map unit_struct + newtype_struct tuple_struct struct struct_field tuple enum + ignored_any + } } impl de::SeqVisitor for Deserializer { From 536e78a146d477b4d89a7c72bb0c865586e37fa1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 18 Oct 2016 22:19:07 -0700 Subject: [PATCH 068/111] Remove benchmarks Nobody noticed these did not compile for 3 months, so I am guessing nobody cares. The JSON benchmarks at https://github.com/serde-rs/json-benchmark are much more relevant. --- testing/Cargo.toml | 4 - testing/benches/bench.rs | 10 - testing/benches/bench.rs.in | 4 - testing/benches/bench_enum.rs | 506 --------------------- testing/benches/bench_map.rs | 481 -------------------- testing/benches/bench_struct.rs | 751 -------------------------------- testing/benches/bench_vec.rs | 642 --------------------------- testing/build.rs | 12 +- 8 files changed, 3 insertions(+), 2407 deletions(-) delete mode 100644 testing/benches/bench.rs delete mode 100644 testing/benches/bench.rs.in delete mode 100644 testing/benches/bench_enum.rs delete mode 100644 testing/benches/bench_map.rs delete mode 100644 testing/benches/bench_struct.rs delete mode 100644 testing/benches/bench_vec.rs diff --git a/testing/Cargo.toml b/testing/Cargo.toml index fb7c04e9..f03987e6 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -29,7 +29,3 @@ clippy = { version = "^0.*", optional = true } [[test]] name = "test" path = "tests/test.rs" - -[[bench]] -name = "bench" -path = "benches/bench.rs" diff --git a/testing/benches/bench.rs b/testing/benches/bench.rs deleted file mode 100644 index 80ebadac..00000000 --- a/testing/benches/bench.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(test)] -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] - -extern crate rustc_serialize; -#[macro_use] -extern crate serde; -extern crate test; - -include!(concat!(env!("OUT_DIR"), "/bench.rs")); diff --git a/testing/benches/bench.rs.in b/testing/benches/bench.rs.in deleted file mode 100644 index d79b35f0..00000000 --- a/testing/benches/bench.rs.in +++ /dev/null @@ -1,4 +0,0 @@ -mod bench_enum; -mod bench_map; -mod bench_struct; -mod bench_vec; diff --git a/testing/benches/bench_enum.rs b/testing/benches/bench_enum.rs deleted file mode 100644 index 0e591c5b..00000000 --- a/testing/benches/bench_enum.rs +++ /dev/null @@ -1,506 +0,0 @@ -use test::Bencher; -use std::error; -use std::fmt; -use rustc_serialize::Decodable; -use serde; -use serde::de::Deserialize; - -////////////////////////////////////////////////////////////////////////////// - -#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)] -pub enum Animal { - Dog, - Frog(String, isize) -} - -////////////////////////////////////////////////////////////////////////////// - -#[derive(Debug)] -pub enum Error { - EndOfStream, - Syntax, -} - -impl serde::de::Error for Error { - fn custom>(_: T) -> Error { Error::Syntax } - - fn end_of_stream() -> Error { Error::EndOfStream } - - fn unknown_field(_: &str) -> Error { Error::Syntax } - - fn missing_field(_: &'static str) -> Error { Error::Syntax } -} - -impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str(format!("{:?}", self).as_ref()) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - "Serde Deserialization Error" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} - -////////////////////////////////////////////////////////////////////////////// - -mod decoder { - use rustc_serialize::Decoder; - - use super::{Animal, Error}; - use super::Animal::{Dog, Frog}; - - enum State { - Animal(Animal), - Isize(isize), - String(String), - } - - pub struct AnimalDecoder { - stack: Vec, - - } - - impl AnimalDecoder { - #[inline] - pub fn new(animal: Animal) -> AnimalDecoder { - AnimalDecoder { - stack: vec!(State::Animal(animal)), - } - } - } - - impl Decoder for AnimalDecoder { - type Error = Error; - - fn error(&mut self, _: &str) -> Error { Error::Syntax } - - // Primitive types: - fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) } - fn read_usize(&mut self) -> Result { Err(Error::Syntax) } - fn read_u64(&mut self) -> Result { Err(Error::Syntax) } - fn read_u32(&mut self) -> Result { Err(Error::Syntax) } - fn read_u16(&mut self) -> Result { Err(Error::Syntax) } - fn read_u8(&mut self) -> Result { Err(Error::Syntax) } - #[inline] - fn read_isize(&mut self) -> Result { - match self.stack.pop() { - Some(State::Isize(x)) => Ok(x), - _ => Err(Error::Syntax), - } - } - fn read_i64(&mut self) -> Result { Err(Error::Syntax) } - fn read_i32(&mut self) -> Result { Err(Error::Syntax) } - fn read_i16(&mut self) -> Result { Err(Error::Syntax) } - fn read_i8(&mut self) -> Result { Err(Error::Syntax) } - fn read_bool(&mut self) -> Result { Err(Error::Syntax) } - fn read_f64(&mut self) -> Result { Err(Error::Syntax) } - fn read_f32(&mut self) -> Result { Err(Error::Syntax) } - fn read_char(&mut self) -> Result { Err(Error::Syntax) } - #[inline] - fn read_str(&mut self) -> Result { - match self.stack.pop() { - Some(State::String(x)) => Ok(x), - _ => Err(Error::Syntax), - } - } - - // Compound types: - #[inline] - fn read_enum(&mut self, name: &str, f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - match self.stack.pop() { - Some(State::Animal(animal)) => { - self.stack.push(State::Animal(animal)); - if name == "Animal" { - f(self) - } else { - Err(Error::Syntax) - } - } - _ => Err(Error::Syntax) - } - } - - #[inline] - fn read_enum_variant(&mut self, names: &[&str], f: F) -> Result where - F: FnOnce(&mut AnimalDecoder, usize) -> Result, - { - let name = match self.stack.pop() { - Some(State::Animal(Dog)) => "Dog", - Some(State::Animal(Frog(x0, x1))) => { - self.stack.push(State::Isize(x1)); - self.stack.push(State::String(x0)); - "Frog" - } - _ => { return Err(Error::Syntax); } - }; - - let idx = match names.iter().position(|n| *n == name) { - Some(idx) => idx, - None => { return Err(Error::Syntax); } - }; - - f(self, idx) - } - - #[inline] - fn read_enum_variant_arg(&mut self, _a_idx: usize, f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - f(self) - } - - fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple(&mut self, _len: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - // Specialized types: - fn read_option(&mut self, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder, bool) -> Result, - { - Err(Error::Syntax) - } - - #[inline] - fn read_seq(&mut self, f: F) -> Result where - F: FnOnce(&mut AnimalDecoder, usize) -> Result, - { - f(self, 3) - } - - #[inline] - fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - f(self) - } - - fn read_map(&mut self, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_map_elt_key(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_map_elt_val(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut AnimalDecoder) -> Result, - { - Err(Error::Syntax) - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -mod deserializer { - use super::{Animal, Error}; - - use serde::de::{self, Deserialize}; - - #[derive(Debug)] - enum State { - Animal(Animal), - Isize(isize), - Str(&'static str), - String(String), - UnitState, - } - - pub struct AnimalDeserializer { - stack: Vec, - } - - impl AnimalDeserializer { - #[inline] - pub fn new(animal: Animal) -> AnimalDeserializer { - AnimalDeserializer { - stack: vec!(State::Animal(animal)), - } - } - } - - impl de::Deserializer for AnimalDeserializer { - type Error = Error; - - #[inline] - fn deserialize(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - match self.stack.pop() { - Some(State::Isize(value)) => { - visitor.visit_isize(value) - } - Some(State::String(value)) => { - visitor.visit_string(value) - } - Some(State::Str(value)) => { - visitor.visit_str(value) - } - Some(State::UnitState) => { - visitor.visit_unit() - } - Some(_) => { - Err(Error::Syntax) - } - None => { - Err(Error::EndOfStream) - } - } - } - - #[inline] - fn deserialize_enum(&mut self, - _name: &str, - _variants: &[&str], - mut visitor: V) -> Result - where V: de::EnumVisitor, - { - match self.stack.pop() { - Some(State::Animal(Animal::Dog)) => { - self.stack.push(State::UnitState); - self.stack.push(State::Str("Dog")); - visitor.visit(DogVisitor { - de: self, - }) - } - Some(State::Animal(Animal::Frog(x0, x1))) => { - self.stack.push(State::Isize(x1)); - self.stack.push(State::String(x0)); - self.stack.push(State::Str("Frog")); - visitor.visit(FrogVisitor { - de: self, - state: 0, - }) - } - Some(_) => { - Err(Error::Syntax) - } - None => { - Err(Error::EndOfStream) - } - } - } - - forward_to_deserialize! { - bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str - string unit option seq seq_fixed_size bytes map unit_struct - newtype_struct tuple_struct struct struct_field tuple ignored_any - } - } - - struct DogVisitor<'a> { - de: &'a mut AnimalDeserializer, - } - - impl<'a> de::VariantVisitor for DogVisitor<'a> { - type Error = Error; - - fn visit_variant(&mut self) -> Result - where V: de::Deserialize - { - de::Deserialize::deserialize(self.de) - } - - fn visit_unit(&mut self) -> Result<(), Error> { - de::Deserialize::deserialize(self.de) - } - - fn visit_newtype(&mut self) -> Result - where T: Deserialize - { - Err(de::Error::invalid_type(de::Type::TupleVariant)) - } - - fn visit_tuple(&mut self, _len: usize, _visitor: V) -> Result - where V: de::Visitor - { - Err(de::Error::invalid_type(de::Type::TupleVariant)) - } - - fn visit_struct(&mut self, _fields: &'static [&'static str], _visitor: V) -> Result - where V: de::Visitor - { - Err(de::Error::invalid_type(de::Type::StructVariant)) - } - } - - struct FrogVisitor<'a> { - de: &'a mut AnimalDeserializer, - state: usize, - } - - impl<'a> de::VariantVisitor for FrogVisitor<'a> { - type Error = Error; - - fn visit_variant(&mut self) -> Result - where V: de::Deserialize - { - de::Deserialize::deserialize(self.de) - } - - fn visit_tuple(&mut self, - _len: usize, - mut visitor: V) -> Result - where V: de::Visitor, - { - visitor.visit_seq(self) - } - - fn visit_unit(&mut self) -> Result<(), Error> { - Err(de::Error::invalid_type(de::Type::UnitVariant)) - } - - fn visit_newtype(&mut self) -> Result - where T: Deserialize - { - Err(de::Error::invalid_type(de::Type::TupleVariant)) - } - - fn visit_struct(&mut self, _fields: &'static [&'static str], _visitor: V) -> Result - where V: de::Visitor - { - Err(de::Error::invalid_type(de::Type::StructVariant)) - } - } - - impl<'a> de::SeqVisitor for FrogVisitor<'a> { - type Error = Error; - - fn visit(&mut self) -> Result, Error> - where T: de::Deserialize, - { - match self.state { - 0 => { - self.state += 1; - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - 1 => { - self.state += 1; - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - _ => { - Ok(None) - } - } - } - - fn end(&mut self) -> Result<(), Error> { - if self.state == 2 { - Ok(()) - } else { - Err(Error::Syntax) - } - } - - fn size_hint(&self) -> (usize, Option) { - let len = 2 - self.state; - (len, Some(len)) - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -#[bench] -fn bench_decoder_dog(b: &mut Bencher) { - b.iter(|| { - let animal = Animal::Dog; - - let mut d = decoder::AnimalDecoder::new(animal.clone()); - let value: Animal = Decodable::decode(&mut d).unwrap(); - - assert_eq!(value, animal); - }) -} - -#[bench] -fn bench_decoder_frog(b: &mut Bencher) { - b.iter(|| { - let animal = Animal::Frog("Henry".to_owned(), 349); - - let mut d = decoder::AnimalDecoder::new(animal.clone()); - let value: Animal = Decodable::decode(&mut d).unwrap(); - - assert_eq!(value, animal); - }) -} - -#[bench] -fn bench_deserializer_dog(b: &mut Bencher) { - b.iter(|| { - let animal = Animal::Dog; - - let mut d = deserializer::AnimalDeserializer::new(animal.clone()); - let value: Animal = Deserialize::deserialize(&mut d).unwrap(); - - assert_eq!(value, animal); - }) -} - -#[bench] -fn bench_deserializer_frog(b: &mut Bencher) { - b.iter(|| { - let animal = Animal::Frog("Henry".to_owned(), 349); - - let mut d = deserializer::AnimalDeserializer::new(animal.clone()); - let value: Animal = Deserialize::deserialize(&mut d).unwrap(); - - assert_eq!(value, animal); - }) -} diff --git a/testing/benches/bench_map.rs b/testing/benches/bench_map.rs deleted file mode 100644 index bd2bb70f..00000000 --- a/testing/benches/bench_map.rs +++ /dev/null @@ -1,481 +0,0 @@ -use std::fmt::Debug; -use std::fmt; -use std::error; -use std::collections::HashMap; -use test::Bencher; - -use rustc_serialize::{Decoder, Decodable}; - -use serde; -use serde::de::{Deserializer, Deserialize}; - -////////////////////////////////////////////////////////////////////////////// - -#[derive(PartialEq, Debug)] -pub enum Error { - EndOfStream, - Syntax, - MissingField, -} - -impl serde::de::Error for Error { - fn custom>(_: T) -> Error { Error::Syntax } - - fn end_of_stream() -> Error { Error::EndOfStream } - - fn unknown_field(_: &str) -> Error { Error::Syntax } - - fn missing_field(_: &'static str) -> Error { - Error::MissingField - } -} - -impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str(format!("{:?}", self).as_ref()) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - "Serde Deserialization Error" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} -////////////////////////////////////////////////////////////////////////////// - -mod decoder { - use std::collections::HashMap; - use std::collections::hash_map::IntoIter; - use rustc_serialize; - - use super::Error; - - enum Value { - String(String), - Isize(isize), - } - - pub struct IsizeDecoder { - len: usize, - iter: IntoIter, - stack: Vec, - } - - impl IsizeDecoder { - #[inline] - pub fn new(values: HashMap) -> IsizeDecoder { - IsizeDecoder { - len: values.len(), - iter: values.into_iter(), - stack: vec!(), - } - } - } - - impl rustc_serialize::Decoder for IsizeDecoder { - type Error = Error; - - fn error(&mut self, _msg: &str) -> Error { - Error::Syntax - } - - // Primitive types: - fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) } - fn read_usize(&mut self) -> Result { Err(Error::Syntax) } - fn read_u64(&mut self) -> Result { Err(Error::Syntax) } - fn read_u32(&mut self) -> Result { Err(Error::Syntax) } - fn read_u16(&mut self) -> Result { Err(Error::Syntax) } - fn read_u8(&mut self) -> Result { Err(Error::Syntax) } - #[inline] - fn read_isize(&mut self) -> Result { - match self.stack.pop() { - Some(Value::Isize(x)) => Ok(x), - Some(_) => Err(Error::Syntax), - None => Err(Error::EndOfStream), - } - } - fn read_i64(&mut self) -> Result { Err(Error::Syntax) } - fn read_i32(&mut self) -> Result { Err(Error::Syntax) } - fn read_i16(&mut self) -> Result { Err(Error::Syntax) } - fn read_i8(&mut self) -> Result { Err(Error::Syntax) } - fn read_bool(&mut self) -> Result { Err(Error::Syntax) } - fn read_f64(&mut self) -> Result { Err(Error::Syntax) } - fn read_f32(&mut self) -> Result { Err(Error::Syntax) } - fn read_char(&mut self) -> Result { Err(Error::Syntax) } - #[inline] - fn read_str(&mut self) -> Result { - match self.stack.pop() { - Some(Value::String(x)) => Ok(x), - Some(_) => Err(Error::Syntax), - None => Err(Error::EndOfStream), - } - } - - // Compound types: - fn read_enum(&mut self, _name: &str, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple(&mut self, _len: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - // Specialized types: - fn read_option(&mut self, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder, bool) -> Result, - { - Err(Error::Syntax) - } - - fn read_seq(&mut self, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_seq_elt(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - #[inline] - fn read_map(&mut self, f: F) -> Result where - F: FnOnce(&mut IsizeDecoder, usize) -> Result, - { - let len = self.len; - f(self, len) - } - #[inline] - fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - match self.iter.next() { - Some((key, value)) => { - self.stack.push(Value::Isize(value)); - self.stack.push(Value::String(key)); - f(self) - } - None => { - Err(Error::Syntax) - } - } - } - - #[inline] - fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut IsizeDecoder) -> Result, - { - f(self) - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -mod deserializer { - use std::collections::HashMap; - use std::collections::hash_map; - - use super::Error; - - use serde::de; - - #[derive(PartialEq, Debug)] - enum State { - StartState, - Key(String), - Value(isize), - } - - pub struct IsizeDeserializer { - stack: Vec, - iter: hash_map::IntoIter, - } - - impl IsizeDeserializer { - #[inline] - pub fn new(values: HashMap) -> IsizeDeserializer { - IsizeDeserializer { - stack: vec!(State::StartState), - iter: values.into_iter(), - } - } - } - - impl de::Deserializer for IsizeDeserializer { - type Error = Error; - - fn deserialize(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - match self.stack.pop() { - Some(State::StartState) => { - visitor.visit_map(self) - } - Some(State::Key(key)) => { - visitor.visit_string(key) - } - Some(State::Value(value)) => { - visitor.visit_isize(value) - } - None => { - Err(Error::EndOfStream) - } - } - } - - forward_to_deserialize! { - bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str - string unit option seq seq_fixed_size bytes map unit_struct - newtype_struct tuple_struct struct struct_field tuple enum - ignored_any - } - } - - impl de::MapVisitor for IsizeDeserializer { - type Error = Error; - - fn visit_key(&mut self) -> Result, Error> - where K: de::Deserialize, - { - match self.iter.next() { - Some((key, value)) => { - self.stack.push(State::Value(value)); - self.stack.push(State::Key(key)); - Ok(Some(try!(de::Deserialize::deserialize(self)))) - } - None => { - Ok(None) - } - } - } - - fn visit_value(&mut self) -> Result - where V: de::Deserialize, - { - de::Deserialize::deserialize(self) - } - - fn end(&mut self) -> Result<(), Error> { - match self.iter.next() { - Some(_) => Err(Error::Syntax), - None => Ok(()), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - } - -/* - impl Iterator for IsizeDeserializer { - type Item = Result; - - #[inline] - fn next(&mut self) -> Option> { - match self.stack.pop() { - Some(State::StartState) => { - self.stack.push(KeyOrEndState); - Some(Ok(de::Token::MapStart(self.len))) - } - Some(State::KeyOrEndState) => { - match self.iter.next() { - Some((key, value)) => { - self.stack.push(Value(value)); - Some(Ok(de::Token::String(key))) - } - None => { - self.stack.push(EndState); - Some(Ok(de::Token::End)) - } - } - } - Some(State::Value(x)) => { - self.stack.push(KeyOrEndState); - Some(Ok(de::Token::Isize(x))) - } - Some(EndState) => { - None - } - None => { - None - } - } - } - } - - impl de::Deserializer for IsizeDeserializer { - #[inline] - fn end_of_stream(&mut self) -> Error { - EndOfStream - } - - #[inline] - fn syntax(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error { - Syntax - } - - #[inline] - fn unexpected_name(&mut self, _token: de::Token) -> Error { - Syntax - } - - #[inline] - fn conversion_error(&mut self, _token: de::Token) -> Error { - Syntax - } - - #[inline] - fn missing_field< - T: de::Deserialize - >(&mut self, _field: &'static str) -> Result { - Err(Error::Syntax) - } - } -*/ -} - -////////////////////////////////////////////////////////////////////////////// - -fn run_decoder< - D: Decoder, - T: Clone + PartialEq + Debug + Decodable ->(mut d: D, value: T) { - let v = Decodable::decode(&mut d); - - assert_eq!(Ok(value), v); -} - -#[bench] -fn bench_decoder_000(b: &mut Bencher) { - b.iter(|| { - let m: HashMap = HashMap::new(); - run_decoder(decoder::IsizeDecoder::new(m.clone()), m) - }) -} - -#[bench] -fn bench_decoder_003(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = HashMap::new(); - for i in 0 .. 3 { - m.insert(i.to_string(), i); - } - run_decoder(decoder::IsizeDecoder::new(m.clone()), m) - }) -} - -#[bench] -fn bench_decoder_100(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = HashMap::new(); - for i in 0 .. 100 { - m.insert(i.to_string(), i); - } - run_decoder(decoder::IsizeDecoder::new(m.clone()), m) - }) -} - -fn run_deserializer(mut d: D, value: T) - where D: Deserializer, - D::Error: Debug + PartialEq, - T: Clone + PartialEq + Debug + Deserialize -{ - let v = T::deserialize(&mut d); - - assert_eq!(Ok(value), v); -} - -#[bench] -fn bench_deserializer_000(b: &mut Bencher) { - b.iter(|| { - let m: HashMap = HashMap::new(); - run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m) - }) -} - -#[bench] -fn bench_deserializer_003(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = HashMap::new(); - for i in 0 .. 3 { - m.insert(i.to_string(), i); - } - run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m) - }) -} - -#[bench] -fn bench_deserializer_100(b: &mut Bencher) { - b.iter(|| { - let mut m: HashMap = HashMap::new(); - for i in 0 .. 100 { - m.insert(i.to_string(), i); - } - run_deserializer(deserializer::IsizeDeserializer::new(m.clone()), m) - }) -} diff --git a/testing/benches/bench_struct.rs b/testing/benches/bench_struct.rs deleted file mode 100644 index 305de666..00000000 --- a/testing/benches/bench_struct.rs +++ /dev/null @@ -1,751 +0,0 @@ -use std::collections::HashMap; -use test::Bencher; -use std::fmt; -use std::error; - -use rustc_serialize::Decodable; - -use serde; -use serde::de::Deserialize; - -////////////////////////////////////////////////////////////////////////////// - -#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)] -pub struct Inner { - a: (), - b: usize, - c: HashMap>, -} - -////////////////////////////////////////////////////////////////////////////// - -#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)] -pub struct Outer { - inner: Vec, -} - -////////////////////////////////////////////////////////////////////////////// - -#[derive(Debug, PartialEq)] -pub enum Error { - EndOfStream, - Syntax, - MissingField, - OtherError, -} - -impl serde::de::Error for Error { - fn custom>(_: T) -> Error { Error::Syntax } - - fn end_of_stream() -> Error { Error::EndOfStream } - - fn unknown_field(_: &str) -> Error { Error::Syntax } - - fn missing_field(_: &'static str) -> Error { - Error::MissingField - } -} - -impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str(format!("{:?}", self).as_ref()) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - "Serde Deserialization Error" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} - -mod decoder { - use std::collections::HashMap; - use rustc_serialize::Decoder; - - use super::{Outer, Inner, Error}; - - #[derive(Debug)] - enum State { - Outer(Outer), - Inner(Inner), - Null, - Usize(usize), - Char(char), - String(String), - Field(&'static str), - Vec(Vec), - Map(HashMap>), - Option(bool), - } - - pub struct OuterDecoder { - stack: Vec, - - } - - impl OuterDecoder { - #[inline] - pub fn new(animal: Outer) -> OuterDecoder { - OuterDecoder { - stack: vec!(State::Outer(animal)), - } - } - } - - impl Decoder for OuterDecoder { - type Error = Error; - - fn error(&mut self, _msg: &str) -> Error { - Error::OtherError - } - - // Primitive types: - #[inline] - fn read_nil(&mut self) -> Result<(), Error> { - match self.stack.pop() { - Some(State::Null) => Ok(()), - _ => Err(Error::Syntax), - } - } - #[inline] - fn read_usize(&mut self) -> Result { - match self.stack.pop() { - Some(State::Usize(value)) => Ok(value), - _ => Err(Error::Syntax), - } - } - fn read_u64(&mut self) -> Result { Err(Error::Syntax) } - fn read_u32(&mut self) -> Result { Err(Error::Syntax) } - fn read_u16(&mut self) -> Result { Err(Error::Syntax) } - fn read_u8(&mut self) -> Result { Err(Error::Syntax) } - fn read_isize(&mut self) -> Result { Err(Error::Syntax) } - fn read_i64(&mut self) -> Result { Err(Error::Syntax) } - fn read_i32(&mut self) -> Result { Err(Error::Syntax) } - fn read_i16(&mut self) -> Result { Err(Error::Syntax) } - fn read_i8(&mut self) -> Result { Err(Error::Syntax) } - fn read_bool(&mut self) -> Result { Err(Error::Syntax) } - fn read_f64(&mut self) -> Result { Err(Error::Syntax) } - fn read_f32(&mut self) -> Result { Err(Error::Syntax) } - #[inline] - fn read_char(&mut self) -> Result { - match self.stack.pop() { - Some(State::Char(c)) => Ok(c), - _ => Err(Error::Syntax), - } - } - #[inline] - fn read_str(&mut self) -> Result { - match self.stack.pop() { - Some(State::String(value)) => Ok(value), - _ => Err(Error::Syntax), - } - } - - // Compound types: - fn read_enum(&mut self, _name: &str, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut OuterDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut OuterDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - #[inline] - fn read_struct(&mut self, s_name: &str, _len: usize, f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - match self.stack.pop() { - Some(State::Outer(Outer { inner })) => { - if s_name == "Outer" { - self.stack.push(State::Vec(inner)); - self.stack.push(State::Field("inner")); - f(self) - } else { - Err(Error::Syntax) - } - } - Some(State::Inner(Inner { a: (), b, c })) => { - if s_name == "Inner" { - self.stack.push(State::Map(c)); - self.stack.push(State::Field("c")); - - self.stack.push(State::Usize(b)); - self.stack.push(State::Field("b")); - - self.stack.push(State::Null); - self.stack.push(State::Field("a")); - f(self) - } else { - Err(Error::Syntax) - } - } - _ => Err(Error::Syntax), - } - } - #[inline] - fn read_struct_field(&mut self, f_name: &str, _f_idx: usize, f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - match self.stack.pop() { - Some(State::Field(name)) => { - if f_name == name { - f(self) - } else { - Err(Error::Syntax) - } - } - _ => Err(Error::Syntax) - } - } - - fn read_tuple(&mut self, _len: usize, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - Err(Error::Syntax) - } - - // Specialized types: - #[inline] - fn read_option(&mut self, f: F) -> Result where - F: FnOnce(&mut OuterDecoder, bool) -> Result, - { - match self.stack.pop() { - Some(State::Option(b)) => f(self, b), - _ => Err(Error::Syntax), - } - } - - #[inline] - fn read_seq(&mut self, f: F) -> Result where - F: FnOnce(&mut OuterDecoder, usize) -> Result, - { - match self.stack.pop() { - Some(State::Vec(value)) => { - let len = value.len(); - for inner in value.into_iter().rev() { - self.stack.push(State::Inner(inner)); - } - f(self, len) - } - _ => Err(Error::Syntax) - } - } - #[inline] - fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - f(self) - } - - #[inline] - fn read_map(&mut self, f: F) -> Result where - F: FnOnce(&mut OuterDecoder, usize) -> Result, - { - match self.stack.pop() { - Some(State::Map(map)) => { - let len = map.len(); - for (key, value) in map { - match value { - Some(c) => { - self.stack.push(State::Char(c)); - self.stack.push(State::Option(true)); - } - None => { - self.stack.push(State::Option(false)); - } - } - self.stack.push(State::String(key)); - } - f(self, len) - } - _ => Err(Error::Syntax), - } - } - #[inline] - fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - f(self) - } - - #[inline] - fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut OuterDecoder) -> Result, - { - f(self) - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -mod deserializer { - use std::collections::HashMap; - use std::collections::hash_map; - use std::vec; - use super::{Outer, Inner}; - use super::Error; - use serde::de; - - #[derive(Debug)] - enum State { - Outer(Outer), - Inner(Inner), - Str(&'static str), - Null, - Usize(usize), - Char(char), - String(String), - Option(bool), - Vec(Vec), - Map(HashMap>), - } - - pub struct OuterDeserializer { - stack: Vec, - } - - impl OuterDeserializer { - #[inline] - pub fn new(outer: Outer) -> OuterDeserializer { - OuterDeserializer { - stack: vec!(State::Outer(outer)), - } - } - } - - impl de::Deserializer for OuterDeserializer { - type Error = Error; - - fn deserialize(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - match self.stack.pop() { - Some(State::Vec(value)) => { - visitor.visit_seq(OuterSeqVisitor { - de: self, - iter: value.into_iter(), - }) - } - Some(State::Map(value)) => { - visitor.visit_map(MapVisitor { - de: self, - iter: value.into_iter(), - }) - } - Some(State::Null) => { - visitor.visit_unit() - } - Some(State::Usize(x)) => { - visitor.visit_usize(x) - } - Some(State::Char(x)) => { - visitor.visit_char(x) - } - Some(State::Str(x)) => { - visitor.visit_str(x) - } - Some(State::String(x)) => { - visitor.visit_string(x) - } - Some(State::Option(false)) => { - visitor.visit_none() - } - Some(State::Option(true)) => { - visitor.visit_some(self) - } - Some(_) => Err(Error::Syntax), - None => Err(Error::EndOfStream), - } - } - - fn deserialize_struct(&mut self, - name: &str, - _fields: &'static [&'static str], - mut visitor: V) -> Result - where V: de::Visitor, - { - match self.stack.pop() { - Some(State::Outer(Outer { inner })) => { - if name != "Outer" { - return Err(Error::Syntax); - } - - self.stack.push(State::Vec(inner)); - self.stack.push(State::Str("inner")); - - visitor.visit_map(OuterMapVisitor { - de: self, - state: 0, - }) - } - Some(State::Inner(Inner { a: (), b, c })) => { - if name != "Inner" { - return Err(Error::Syntax); - } - - self.stack.push(State::Map(c)); - self.stack.push(State::Str("c")); - - self.stack.push(State::Usize(b)); - self.stack.push(State::Str("b")); - - self.stack.push(State::Null); - self.stack.push(State::Str("a")); - - visitor.visit_map(InnerMapVisitor { - de: self, - state: 0, - }) - } - _ => { - Err(Error::Syntax) - } - } - } - - forward_to_deserialize! { - bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str - string unit option seq seq_fixed_size bytes map unit_struct - newtype_struct tuple_struct struct_field tuple enum ignored_any - } - } - - struct OuterMapVisitor<'a> { - de: &'a mut OuterDeserializer, - state: usize, - } - - impl<'a> de::MapVisitor for OuterMapVisitor<'a> { - type Error = Error; - - fn visit_key(&mut self) -> Result, Error> - where K: de::Deserialize, - { - match self.state { - 0 => { - self.state += 1; - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - _ => { - Ok(None) - } - } - } - - fn visit_value(&mut self) -> Result - where V: de::Deserialize, - { - de::Deserialize::deserialize(self.de) - } - - fn end(&mut self) -> Result<(), Error> { - if self.state == 1 { - Ok(()) - } else { - Err(Error::Syntax) - } - } - - fn size_hint(&self) -> (usize, Option) { - let len = 1 - self.state; - (len, Some(len)) - } - } - - struct OuterSeqVisitor<'a> { - de: &'a mut OuterDeserializer, - iter: vec::IntoIter, - } - - impl<'a> de::SeqVisitor for OuterSeqVisitor<'a> { - type Error = Error; - - fn visit(&mut self) -> Result, Error> - where T: de::Deserialize, - { - match self.iter.next() { - Some(value) => { - self.de.stack.push(State::Inner(value)); - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - None => { - Ok(None) - } - } - } - - fn end(&mut self) -> Result<(), Error> { - match self.iter.next() { - Some(_) => Err(Error::Syntax), - None => Ok(()), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - } - - struct InnerMapVisitor<'a> { - de: &'a mut OuterDeserializer, - state: usize, - } - - impl<'a> de::MapVisitor for InnerMapVisitor<'a> { - type Error = Error; - - fn visit_key(&mut self) -> Result, Error> - where K: de::Deserialize, - { - match self.state { - 0 ... 2 => { - self.state += 1; - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - _ => { - Ok(None) - } - } - } - - fn visit_value(&mut self) -> Result - where V: de::Deserialize, - { - de::Deserialize::deserialize(self.de) - } - - fn end(&mut self) -> Result<(), Error> { - if self.state == 3 { - Ok(()) - } else { - Err(Error::Syntax) - } - } - - fn size_hint(&self) -> (usize, Option) { - let len = 1 - self.state; - (len, Some(len)) - } - } - - struct MapVisitor<'a> { - de: &'a mut OuterDeserializer, - iter: hash_map::IntoIter>, - } - - impl<'a> de::MapVisitor for MapVisitor<'a> { - type Error = Error; - - fn visit_key(&mut self) -> Result, Error> - where K: de::Deserialize, - { - match self.iter.next() { - Some((key, Some(value))) => { - self.de.stack.push(State::Char(value)); - self.de.stack.push(State::Option(true)); - self.de.stack.push(State::String(key)); - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - Some((key, None)) => { - self.de.stack.push(State::Option(false)); - self.de.stack.push(State::String(key)); - Ok(Some(try!(de::Deserialize::deserialize(self.de)))) - } - None => { - Ok(None) - } - } - } - - fn visit_value(&mut self) -> Result - where V: de::Deserialize, - { - de::Deserialize::deserialize(self.de) - } - - fn end(&mut self) -> Result<(), Error> { - match self.iter.next() { - Some(_) => Err(Error::Syntax), - None => Ok(()), - } - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - } -} - -#[bench] -fn bench_decoder_0_0(b: &mut Bencher) { - b.iter(|| { - let mut map = HashMap::new(); - map.insert("abc".to_owned(), Some('c')); - - let outer = Outer { - inner: vec!(), - }; - - let mut d = decoder::OuterDecoder::new(outer.clone()); - let value: Result = Decodable::decode(&mut d); - - assert_eq!(value, Ok(outer)); - }) -} - -#[bench] -fn bench_decoder_1_0(b: &mut Bencher) { - b.iter(|| { - let map = HashMap::new(); - - let outer = Outer { - inner: vec!( - Inner { - a: (), - b: 5, - c: map, - }, - ) - }; - - let mut d = decoder::OuterDecoder::new(outer.clone()); - let value: Result = Decodable::decode(&mut d); - - assert_eq!(value, Ok(outer)); - }) -} - -#[bench] -fn bench_decoder_1_5(b: &mut Bencher) { - b.iter(|| { - let mut map = HashMap::new(); - map.insert("1".to_owned(), Some('a')); - map.insert("2".to_owned(), None); - map.insert("3".to_owned(), Some('b')); - map.insert("4".to_owned(), None); - map.insert("5".to_owned(), Some('c')); - - let outer = Outer { - inner: vec!( - Inner { - a: (), - b: 5, - c: map, - }, - ) - }; - - let mut d = decoder::OuterDecoder::new(outer.clone()); - let value: Result = Decodable::decode(&mut d); - - assert_eq!(value, Ok(outer)); - }) -} - -#[bench] -fn bench_deserializer_0_0(b: &mut Bencher) { - b.iter(|| { - let outer = Outer { - inner: vec!(), - }; - - let mut d = deserializer::OuterDeserializer::new(outer.clone()); - let value: Result = Deserialize::deserialize(&mut d); - - assert_eq!(value, Ok(outer)); - }) -} - -#[bench] -fn bench_deserializer_1_0(b: &mut Bencher) { - b.iter(|| { - let map = HashMap::new(); - - let outer = Outer { - inner: vec!( - Inner { - a: (), - b: 5, - c: map, - }, - ) - }; - - let mut d = deserializer::OuterDeserializer::new(outer.clone()); - let value: Result = Deserialize::deserialize(&mut d); - - assert_eq!(value, Ok(outer)); - }) -} - -#[bench] -fn bench_deserializer_1_5(b: &mut Bencher) { - b.iter(|| { - let mut map = HashMap::new(); - map.insert("1".to_owned(), Some('a')); - map.insert("2".to_owned(), None); - map.insert("3".to_owned(), Some('b')); - map.insert("4".to_owned(), None); - map.insert("5".to_owned(), Some('c')); - - let outer = Outer { - inner: vec!( - Inner { - a: (), - b: 5, - c: map, - }, - ) - }; - - let mut d = deserializer::OuterDeserializer::new(outer.clone()); - let value: Result = Deserialize::deserialize(&mut d); - - assert_eq!(value, Ok(outer)); - }) -} diff --git a/testing/benches/bench_vec.rs b/testing/benches/bench_vec.rs deleted file mode 100644 index eb71fae9..00000000 --- a/testing/benches/bench_vec.rs +++ /dev/null @@ -1,642 +0,0 @@ -use std::fmt::Debug; -use std::fmt; -use std::error; -use test::Bencher; - -use rustc_serialize::{Decoder, Decodable}; - -use serde; -use serde::de::{Deserializer, Deserialize}; - -////////////////////////////////////////////////////////////////////////////// - -#[derive(PartialEq, Debug)] -pub enum Error { - EndOfStream, - Syntax, -} - -impl serde::de::Error for Error { - fn custom>(_: T) -> Error { Error::Syntax } - - fn end_of_stream() -> Error { Error::EndOfStream } - - fn unknown_field(_: &str) -> Error { Error::Syntax } - - fn missing_field(_: &'static str) -> Error { Error::Syntax } -} - -impl fmt::Display for Error { - fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { - formatter.write_str(format!("{:?}", self).as_ref()) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - "Serde Deserialization Error" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} -////////////////////////////////////////////////////////////////////////////// - -mod decoder { - use std::vec; - use rustc_serialize; - - use super::Error; - - pub struct UsizeDecoder { - len: usize, - iter: vec::IntoIter, - } - - impl UsizeDecoder { - #[inline] - pub fn new(values: Vec) -> UsizeDecoder { - UsizeDecoder { - len: values.len(), - iter: values.into_iter(), - } - } - } - - impl rustc_serialize::Decoder for UsizeDecoder { - type Error = Error; - - fn error(&mut self, _: &str) -> Error { Error::Syntax } - - // Primitive types: - fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) } - #[inline] - fn read_usize(&mut self) -> Result { - match self.iter.next() { - Some(value) => Ok(value), - None => Err(Error::EndOfStream), - } - } - fn read_u64(&mut self) -> Result { Err(Error::Syntax) } - fn read_u32(&mut self) -> Result { Err(Error::Syntax) } - fn read_u16(&mut self) -> Result { Err(Error::Syntax) } - fn read_u8(&mut self) -> Result { Err(Error::Syntax) } - fn read_isize(&mut self) -> Result { Err(Error::Syntax) } - fn read_i64(&mut self) -> Result { Err(Error::Syntax) } - fn read_i32(&mut self) -> Result { Err(Error::Syntax) } - fn read_i16(&mut self) -> Result { Err(Error::Syntax) } - fn read_i8(&mut self) -> Result { Err(Error::Syntax) } - fn read_bool(&mut self) -> Result { Err(Error::Syntax) } - fn read_f64(&mut self) -> Result { Err(Error::Syntax) } - fn read_f32(&mut self) -> Result { Err(Error::Syntax) } - fn read_char(&mut self) -> Result { Err(Error::Syntax) } - fn read_str(&mut self) -> Result { Err(Error::Syntax) } - - // Compound types: - fn read_enum(&mut self, _name: &str, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple(&mut self, _len: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - // Specialized types: - fn read_option(&mut self, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder, bool) -> Result, - { - Err(Error::Syntax) - } - - #[inline] - fn read_seq(&mut self, f: F) -> Result where - F: FnOnce(&mut UsizeDecoder, usize) -> Result, - { - let len = self.len; - f(self, len) - } - #[inline] - fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - f(self) - } - - fn read_map(&mut self, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_map_elt_key(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_map_elt_val(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut UsizeDecoder) -> Result, - { - Err(Error::Syntax) - } - } - - - pub struct U8Decoder { - len: usize, - iter: vec::IntoIter, - } - - impl U8Decoder { - #[inline] - pub fn new(values: Vec) -> U8Decoder { - U8Decoder { - len: values.len(), - iter: values.into_iter(), - } - } - } - - impl rustc_serialize::Decoder for U8Decoder { - type Error = Error; - - fn error(&mut self, _: &str) -> Error { Error::Syntax } - - // Primitive types: - fn read_nil(&mut self) -> Result<(), Error> { Err(Error::Syntax) } - fn read_usize(&mut self) -> Result { Err(Error::Syntax) } - fn read_u64(&mut self) -> Result { Err(Error::Syntax) } - fn read_u32(&mut self) -> Result { Err(Error::Syntax) } - fn read_u16(&mut self) -> Result { Err(Error::Syntax) } - #[inline] - fn read_u8(&mut self) -> Result { - match self.iter.next() { - Some(value) => Ok(value), - None => Err(Error::EndOfStream), - } - } - #[inline] - fn read_isize(&mut self) -> Result { Err(Error::Syntax) } - fn read_i64(&mut self) -> Result { Err(Error::Syntax) } - fn read_i32(&mut self) -> Result { Err(Error::Syntax) } - fn read_i16(&mut self) -> Result { Err(Error::Syntax) } - fn read_i8(&mut self) -> Result { Err(Error::Syntax) } - fn read_bool(&mut self) -> Result { Err(Error::Syntax) } - fn read_f64(&mut self) -> Result { Err(Error::Syntax) } - fn read_f32(&mut self) -> Result { Err(Error::Syntax) } - fn read_char(&mut self) -> Result { Err(Error::Syntax) } - fn read_str(&mut self) -> Result { Err(Error::Syntax) } - - // Compound types: - fn read_enum(&mut self, _name: &str, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut U8Decoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_variant_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) -> Result where - F: FnOnce(&mut U8Decoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_enum_struct_variant_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_struct_field(&mut self, _f_name: &str, _f_idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple(&mut self, _len: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - // Specialized types: - fn read_option(&mut self, _f: F) -> Result where - F: FnOnce(&mut U8Decoder, bool) -> Result, - { - Err(Error::Syntax) - } - - #[inline] - fn read_seq(&mut self, f: F) -> Result where - F: FnOnce(&mut U8Decoder, usize) -> Result, - { - let len = self.len; - f(self, len) - } - #[inline] - fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - f(self) - } - - fn read_map(&mut self, _f: F) -> Result where - F: FnOnce(&mut U8Decoder, usize) -> Result, - { - Err(Error::Syntax) - } - - fn read_map_elt_key(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - - fn read_map_elt_val(&mut self, _idx: usize, _f: F) -> Result where - F: FnOnce(&mut U8Decoder) -> Result, - { - Err(Error::Syntax) - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -mod deserializer { - //use std::num; - use std::vec; - - use super::Error; - - use serde::de; - - #[derive(PartialEq, Debug)] - enum State { - Start, - SepOrEnd, - End, - } - - pub struct Deserializer { - state: State, - iter: vec::IntoIter, - len: usize, - value: Option, - } - - impl Deserializer { - #[inline] - pub fn new(values: Vec) -> Deserializer { - let len = values.len(); - Deserializer { - state: State::Start, - iter: values.into_iter(), - len: len, - value: None, - } - } - } - - impl de::Deserializer for Deserializer { - type Error = Error; - - #[inline] - fn deserialize(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - match self.state { - State::Start => { - self.state = State::SepOrEnd; - visitor.visit_seq(self) - } - State::SepOrEnd => { - visitor.visit_usize(self.value.take().unwrap()) - } - State::End => { - Err(Error::EndOfStream) - } - } - } - - forward_to_deserialize! { - bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str - string unit option seq seq_fixed_size bytes map unit_struct - newtype_struct tuple_struct struct struct_field tuple enum - ignored_any - } - } - - impl de::SeqVisitor for Deserializer { - type Error = Error; - - #[inline] - fn visit(&mut self) -> Result, Error> - where T: de::Deserialize, - { - match self.iter.next() { - Some(value) => { - self.len -= 1; - self.value = Some(value); - Ok(Some(try!(de::Deserialize::deserialize(self)))) - } - None => { - self.state = State::End; - Ok(None) - } - } - } - - #[inline] - fn end(&mut self) -> Result<(), Error> { - match self.iter.next() { - Some(_) => Err(Error::Syntax), - None => { - self.state = State::End; - Ok(()) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) - } - } - - impl de::Deserializer for Deserializer { - type Error = Error; - - #[inline] - fn deserialize(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - match self.state { - State::Start => { - self.state = State::SepOrEnd; - visitor.visit_seq(self) - } - State::SepOrEnd => { - visitor.visit_u8(self.value.take().unwrap()) - } - State::End => { - Err(Error::EndOfStream) - } - } - } - - forward_to_deserialize! { - bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str - string unit option seq seq_fixed_size bytes map unit_struct - newtype_struct tuple_struct struct struct_field tuple enum - ignored_any - } - } - - impl de::SeqVisitor for Deserializer { - type Error = Error; - - #[inline] - fn visit(&mut self) -> Result, Error> - where T: de::Deserialize, - { - match self.iter.next() { - Some(value) => { - self.len -= 1; - self.value = Some(value); - Ok(Some(try!(de::Deserialize::deserialize(self)))) - } - None => { - self.state = State::End; - Ok(None) - } - } - } - - #[inline] - fn end(&mut self) -> Result<(), Error> { - match self.iter.next() { - Some(_) => Err(Error::Syntax), - None => { - self.state = State::End; - Ok(()) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) - } - } -} - -////////////////////////////////////////////////////////////////////////////// - -fn run_decoder< - D: Decoder, - T: Clone + PartialEq + Debug + Decodable ->(mut d: D, value: T) { - let v = Decodable::decode(&mut d); - - assert_eq!(Ok(value), v); -} - -fn run_deserializer(mut d: D, value: T) - where D: Deserializer, - D::Error: Debug + PartialEq, - T: Clone + PartialEq + Debug + Deserialize -{ - let v = T::deserialize(&mut d); - - assert_eq!(Ok(value), v); -} - -#[bench] -fn bench_decoder_usize_000(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(); - run_decoder(decoder::UsizeDecoder::new(v.clone()), v) - }) -} - -#[bench] -fn bench_decoder_usize_003(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(1, 2, 3); - run_decoder(decoder::UsizeDecoder::new(v.clone()), v) - }) -} - -#[bench] -fn bench_decoder_usize_100(b: &mut Bencher) { - b.iter(|| { - let v: Vec = (0 .. 100).collect(); - run_decoder(decoder::UsizeDecoder::new(v.clone()), v) - }) -} - -#[bench] -fn bench_decoder_u8_000(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(); - run_decoder(decoder::U8Decoder::new(v.clone()), v) - }) -} - -#[bench] -fn bench_decoder_u8_003(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(1, 2, 3); - run_decoder(decoder::U8Decoder::new(v.clone()), v) - }) -} - -#[bench] -fn bench_decoder_u8_100(b: &mut Bencher) { - b.iter(|| { - let v: Vec = (0 .. 100).collect(); - run_decoder(decoder::U8Decoder::new(v.clone()), v) - }) -} - -#[bench] -fn bench_deserializer_usize_000(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(); - run_deserializer(deserializer::Deserializer::new(v.clone()), v) - }) -} - -#[bench] -fn bench_deserializer_usize_003(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(1, 2, 3); - run_deserializer(deserializer::Deserializer::new(v.clone()), v) - }) -} - -#[bench] -fn bench_deserializer_usize_100(b: &mut Bencher) { - b.iter(|| { - let v: Vec = (0 .. 100).collect(); - run_deserializer(deserializer::Deserializer::new(v.clone()), v) - }) -} - -#[bench] -fn bench_deserializer_u8_000(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(); - run_deserializer(deserializer::Deserializer::new(v.clone()), v) - }) -} - -#[bench] -fn bench_deserializer_u8_003(b: &mut Bencher) { - b.iter(|| { - let v: Vec = vec!(1, 2, 3); - run_deserializer(deserializer::Deserializer::new(v.clone()), v) - }) -} - -#[bench] -fn bench_deserializer_u8_100(b: &mut Bencher) { - b.iter(|| { - let v: Vec = (0 .. 100).collect(); - run_deserializer(deserializer::Deserializer::new(v.clone()), v) - }) -} diff --git a/testing/build.rs b/testing/build.rs index ad175e85..bf4a763b 100644 --- a/testing/build.rs +++ b/testing/build.rs @@ -5,13 +5,7 @@ use std::path::Path; fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); - - for &(src, dst) in &[ - ("tests/test.rs.in", "test.rs"), - ("benches/bench.rs.in", "bench.rs"), - ] { - let src = Path::new(src); - let dst = Path::new(&out_dir).join(dst); - serde_codegen::expand(&src, &dst).unwrap(); - } + let src = Path::new("tests/test.rs.in"); + let dst = Path::new(&out_dir).join("test.rs"); + serde_codegen::expand(&src, &dst).unwrap(); } From bb5370b74659490326609032f1d6f5c0be8f93d2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 19 Oct 2016 00:30:23 -0700 Subject: [PATCH 069/111] No longer need `e!` --- serde/src/ser/impls.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 58a1683e..5653a717 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -313,11 +313,6 @@ impl Serialize for () { /////////////////////////////////////////////////////////////////////////////// -// FIXME(rust #19630) Remove this work-around -macro_rules! e { - ($e:expr) => { $e } -} - macro_rules! tuple_impls { ($( $TupleVisitor:ident ($len:expr, $($T:ident),+) { @@ -334,7 +329,7 @@ macro_rules! tuple_impls { { let mut state = try!(serializer.serialize_tuple($len)); $( - try!(serializer.serialize_tuple_elt(&mut state, &e!(self.$idx))); + try!(serializer.serialize_tuple_elt(&mut state, &self.$idx)); )+ serializer.serialize_tuple_end(state) } From 49aca521f1caae1e8ade4c7d2a2ab7f9aa7df78a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Oct 2016 00:01:14 -0700 Subject: [PATCH 070/111] Bump post-expansion dependency --- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 4b2b12fe..4c78104b 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,7 +22,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } -post-expansion = "0.0.2" +post-expansion = "0.1.0" quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.9", features = ["aster", "visit"] } diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 5d1e4176..2f70bef4 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies] -post-expansion = "0.0.2" +post-expansion = "0.1.0" [dependencies.serde_codegen] version = "=0.8.14" From 86f0d0382fa71304fac5589cc1304b2151f4c913 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Oct 2016 00:33:00 -0700 Subject: [PATCH 071/111] Drop coveralls Has not been uploading for months. --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a2e08d0..be03184b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,6 @@ rust: - stable - beta - nightly -addons: - apt: - packages: - - libcurl4-openssl-dev - - libelf-dev - - libdw-dev before_script: - pip install 'travis-cargo<0.2' --user - export PATH=$HOME/.local/bin:$PATH @@ -28,8 +22,6 @@ script: - (cd examples/serde-syntex-example && travis-cargo --skip nightly run) - (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable) - (cd serde && travis-cargo --only stable doc) -after_success: -- (cd testing && travis-cargo --only stable coveralls --no-sudo) env: global: - TRAVIS_CARGO_NIGHTLY_FEATURE="" From 9acb17ab54ce33f3776ff9d1e60519681afacc4f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Oct 2016 08:42:40 -0700 Subject: [PATCH 072/111] Release 0.8.15 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 27ea433c..78feaa8e 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.14" +version = "0.8.15" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 4c78104b..abd9366d 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.14" +version = "0.8.15" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 2f70bef4..97f7170f 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.14" +version = "0.8.15" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -18,7 +18,7 @@ proc-macro = true post-expansion = "0.1.0" [dependencies.serde_codegen] -version = "=0.8.14" +version = "=0.8.15" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -26,5 +26,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.14", path = "../serde" } -serde_test = { version = "0.8.14", path = "../serde_test" } +serde = { version = "0.8.15", path = "../serde" } +serde_test = { version = "0.8.15", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 558569d9..a2769aa4 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.14" +version = "0.8.15" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.14", path = "../serde" } +serde = { version = "0.8.15", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index f03987e6..5455422a 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.14" +version = "0.8.15" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From f75d286b901206f67eaff6865fd2529e3c23d461 Mon Sep 17 00:00:00 2001 From: Cat Plus Plus Date: Sat, 22 Oct 2016 08:00:44 +0200 Subject: [PATCH 073/111] Explictly discard result of visiting IgnoredAny Makes the code generated by `derive(Deserialize)` compile cleanly when `unused_results` lint is enabled. --- serde_codegen/src/de.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 173b68f6..93d7d6cf 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -881,7 +881,7 @@ fn deserialize_map( .map(|&(_, ref name)| { quote! { __Field::#name => { - try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); + let _ = try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); } } }) @@ -892,7 +892,7 @@ fn deserialize_map( None } else { Some(quote! { - _ => { try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); } + _ => { let _ = try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); } }) }; From 7ffea5a71670efa3d27bc368bae140aa515da83a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 21 Oct 2016 23:38:27 -0700 Subject: [PATCH 074/111] Bump syntex to 0.46 --- serde_codegen/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index abd9366d..13d69841 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -26,5 +26,5 @@ post-expansion = "0.1.0" quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.9", features = ["aster", "visit"] } -syntex = { version = "^0.45.0", optional = true } -syntex_syntax = { version = "^0.45.0", optional = true } +syntex = { version = "^0.46.0", optional = true } +syntex_syntax = { version = "^0.46.0", optional = true } From c9612a2f5776bd955cafe910f6a1b2446f698e68 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 22 Oct 2016 00:07:27 -0700 Subject: [PATCH 075/111] Release 0.8.16 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 78feaa8e..5d0ebec3 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.15" +version = "0.8.16" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 13d69841..561f4d23 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.15" +version = "0.8.16" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 97f7170f..eebb63ba 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.15" +version = "0.8.16" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -18,7 +18,7 @@ proc-macro = true post-expansion = "0.1.0" [dependencies.serde_codegen] -version = "=0.8.15" +version = "=0.8.16" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -26,5 +26,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.15", path = "../serde" } -serde_test = { version = "0.8.15", path = "../serde_test" } +serde = { version = "0.8.16", path = "../serde" } +serde_test = { version = "0.8.16", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index a2769aa4..8d651eaa 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.15" +version = "0.8.16" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.15", path = "../serde" } +serde = { version = "0.8.16", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 5455422a..e0fbaea0 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.15" +version = "0.8.16" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From f430d9d1c8eed50eceb70ded76c5398247d31921 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 23 Oct 2016 21:06:50 -0700 Subject: [PATCH 076/111] Remove unneeded type ascription --- serde_codegen/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 371cd841..701f0d53 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -194,7 +194,7 @@ pub fn expand_single_item(item: &str) -> Result { let expanded_de = if de { Some(try!(de::expand_derive_deserialize(&syn_item))) } else { - None:: + None }; let syn_item = post_expansion::strip_attrs_later(syn_item, &["serde"], "serde"); return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string()); From 54802983b8525963926181872159dc1e09e183a6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 2 Nov 2016 08:32:30 -0700 Subject: [PATCH 077/111] Bump syntex to 0.48 --- serde_codegen/Cargo.toml | 4 ++-- serde_codegen/src/lib.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 561f4d23..971b0618 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -26,5 +26,5 @@ post-expansion = "0.1.0" quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.9", features = ["aster", "visit"] } -syntex = { version = "^0.46.0", optional = true } -syntex_syntax = { version = "^0.46.0", optional = true } +syntex = { version = "^0.48.0", optional = true } +syntex_syntax = { version = "^0.48.0", optional = true } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 701f0d53..bad346dd 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -171,9 +171,8 @@ macro_rules! shim { use syntax::parse; let name = stringify!($name).to_string(); - let cfg = Vec::new(); let sess = cx.parse_sess; - let impl_item = parse::parse_item_from_source_str(name, expanded, cfg, sess); + let impl_item = parse::parse_item_from_source_str(name, expanded, sess); push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap())); } }; From c91fca19e1fc7a88c700ff5b5832b11b5d929219 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 2 Nov 2016 09:26:04 -0700 Subject: [PATCH 078/111] Release 0.8.17 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 5d0ebec3..7d1db709 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.16" +version = "0.8.17" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 971b0618..eb289be8 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.16" +version = "0.8.17" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index eebb63ba..5267b5d8 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.16" +version = "0.8.17" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -18,7 +18,7 @@ proc-macro = true post-expansion = "0.1.0" [dependencies.serde_codegen] -version = "=0.8.16" +version = "=0.8.17" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -26,5 +26,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.16", path = "../serde" } -serde_test = { version = "0.8.16", path = "../serde_test" } +serde = { version = "0.8.17", path = "../serde" } +serde_test = { version = "0.8.17", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 8d651eaa..387c2577 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.16" +version = "0.8.17" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.16", path = "../serde" } +serde = { version = "0.8.17", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index e0fbaea0..daf56fe7 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.16" +version = "0.8.17" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 6d40d9e8ecf80e9b7b2c540c02f135613b801623 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 2 Nov 2016 22:52:20 -0700 Subject: [PATCH 079/111] Update codegen internals to syn 0.10 --- serde_codegen_internals/Cargo.toml | 2 +- serde_codegen_internals/src/attr.rs | 66 +++++++++++++++++------------ 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 37065da6..47e6504d 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -15,4 +15,4 @@ unstable-testing = ["clippy"] [dependencies] clippy = { version = "^0.*", optional = true } -syn = "0.9" +syn = "0.10" diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 2f90328d..e3a441e4 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -105,7 +105,7 @@ impl Item { for meta_item in meta_items { match meta_item { // Parse `#[serde(rename="foo")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); @@ -113,7 +113,7 @@ impl Item { } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -121,12 +121,12 @@ impl Item { } // Parse `#[serde(deny_unknown_fields)]` - syn::MetaItem::Word(ref name) if name == "deny_unknown_fields" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "deny_unknown_fields" => { deny_unknown_fields.set_true(); } // Parse `#[serde(bound="D: Serialize")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { ser_bound.set(where_predicates.clone()); de_bound.set(where_predicates); @@ -134,17 +134,21 @@ impl Item { } // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` - syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); de_bound.set_opt(de); } } - _ => { + syn::NestedMetaItem::MetaItem(ref meta_item) => { cx.error(format!("unknown serde container attribute `{}`", meta_item.name())); } + + syn::NestedMetaItem::Literal(_) => { + cx.error(format!("unexpected literal in serde container attribute")); + } } } } @@ -192,7 +196,7 @@ impl Variant { for meta_item in meta_items { match meta_item { // Parse `#[serde(rename="foo")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); @@ -200,17 +204,21 @@ impl Variant { } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); } } - _ => { + syn::NestedMetaItem::MetaItem(ref meta_item) => { cx.error(format!("unknown serde variant attribute `{}`", meta_item.name())); } + + syn::NestedMetaItem::Literal(_) => { + cx.error(format!("unexpected literal in serde variant attribute")); + } } } } @@ -278,7 +286,7 @@ impl Field { for meta_item in meta_items { match meta_item { // Parse `#[serde(rename="foo")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); @@ -286,7 +294,7 @@ impl Field { } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -294,50 +302,50 @@ impl Field { } // Parse `#[serde(default)]` - syn::MetaItem::Word(ref name) if name == "default" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "default" => { default.set(FieldDefault::Default); } // Parse `#[serde(default="...")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "default" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "default" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { default.set(FieldDefault::Path(path)); } } // Parse `#[serde(skip_serializing)]` - syn::MetaItem::Word(ref name) if name == "skip_serializing" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "skip_serializing" => { skip_serializing.set_true(); } // Parse `#[serde(skip_deserializing)]` - syn::MetaItem::Word(ref name) if name == "skip_deserializing" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "skip_deserializing" => { skip_deserializing.set_true(); } // Parse `#[serde(skip_serializing_if="...")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "skip_serializing_if" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { skip_serializing_if.set(path); } } // Parse `#[serde(serialize_with="...")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize_with" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "serialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { serialize_with.set(path); } } // Parse `#[serde(deserialize_with="...")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize_with" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "deserialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { deserialize_with.set(path); } } // Parse `#[serde(bound="D: Serialize")]` - syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { ser_bound.set(where_predicates.clone()); de_bound.set(where_predicates); @@ -345,17 +353,21 @@ impl Field { } // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` - syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); de_bound.set_opt(de); } } - _ => { + syn::NestedMetaItem::MetaItem(ref meta_item) => { cx.error(format!("unknown serde field attribute `{}`", meta_item.name())); } + + syn::NestedMetaItem::Literal(_) => { + cx.error(format!("unexpected literal in serde field attribute")); + } } } } @@ -424,7 +436,7 @@ type SerAndDe = (Option, Option); fn get_ser_and_de( cx: &Ctxt, attr_name: &'static str, - items: &[syn::MetaItem], + items: &[syn::NestedMetaItem], f: F ) -> Result, ()> where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result, @@ -434,13 +446,13 @@ fn get_ser_and_de( for item in items { match *item { - syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "serialize" => { if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) { ser_item.set(v); } } - syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize" => { + syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "deserialize" => { if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) { de_item.set(v); } @@ -459,19 +471,19 @@ fn get_ser_and_de( fn get_renames( cx: &Ctxt, - items: &[syn::MetaItem], + items: &[syn::NestedMetaItem], ) -> Result, ()> { get_ser_and_de(cx, "rename", items, get_string_from_lit) } fn get_where_predicates( cx: &Ctxt, - items: &[syn::MetaItem], + items: &[syn::NestedMetaItem], ) -> Result>, ()> { get_ser_and_de(cx, "bound", items, parse_lit_into_where) } -pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> { +pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> { match attr.value { syn::MetaItem::List(ref name, ref items) if name == "serde" => { Some(items.iter().cloned().collect()) From f8c3d225a3b9e4a1b8bce756fcae32c0bc2872c2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 2 Nov 2016 22:56:27 -0700 Subject: [PATCH 080/111] Shorten the syn meta item matches --- serde_codegen_internals/src/attr.rs | 56 +++++++++++++++-------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index e3a441e4..124592dc 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -1,5 +1,7 @@ use Ctxt; use syn; +use syn::MetaItem::{List, NameValue, Word}; +use syn::NestedMetaItem::{Literal, MetaItem}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints // are `attr::Item::from_ast`, `attr::Variant::from_ast`, and @@ -105,7 +107,7 @@ impl Item { for meta_item in meta_items { match meta_item { // Parse `#[serde(rename="foo")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "rename" => { + MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); @@ -113,7 +115,7 @@ impl Item { } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "rename" => { + MetaItem(List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -121,12 +123,12 @@ impl Item { } // Parse `#[serde(deny_unknown_fields)]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "deny_unknown_fields" => { + MetaItem(Word(ref name)) if name == "deny_unknown_fields" => { deny_unknown_fields.set_true(); } // Parse `#[serde(bound="D: Serialize")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "bound" => { + MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { ser_bound.set(where_predicates.clone()); de_bound.set(where_predicates); @@ -134,19 +136,19 @@ impl Item { } // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "bound" => { + MetaItem(List(ref name, ref meta_items)) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); de_bound.set_opt(de); } } - syn::NestedMetaItem::MetaItem(ref meta_item) => { + MetaItem(ref meta_item) => { cx.error(format!("unknown serde container attribute `{}`", meta_item.name())); } - syn::NestedMetaItem::Literal(_) => { + Literal(_) => { cx.error(format!("unexpected literal in serde container attribute")); } } @@ -196,7 +198,7 @@ impl Variant { for meta_item in meta_items { match meta_item { // Parse `#[serde(rename="foo")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "rename" => { + MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); @@ -204,19 +206,19 @@ impl Variant { } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "rename" => { + MetaItem(List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); } } - syn::NestedMetaItem::MetaItem(ref meta_item) => { + MetaItem(ref meta_item) => { cx.error(format!("unknown serde variant attribute `{}`", meta_item.name())); } - syn::NestedMetaItem::Literal(_) => { + Literal(_) => { cx.error(format!("unexpected literal in serde variant attribute")); } } @@ -286,7 +288,7 @@ impl Field { for meta_item in meta_items { match meta_item { // Parse `#[serde(rename="foo")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "rename" => { + MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { ser_name.set(s.clone()); de_name.set(s); @@ -294,7 +296,7 @@ impl Field { } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "rename" => { + MetaItem(List(ref name, ref meta_items)) if name == "rename" => { if let Ok((ser, de)) = get_renames(cx, meta_items) { ser_name.set_opt(ser); de_name.set_opt(de); @@ -302,50 +304,50 @@ impl Field { } // Parse `#[serde(default)]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "default" => { + MetaItem(Word(ref name)) if name == "default" => { default.set(FieldDefault::Default); } // Parse `#[serde(default="...")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "default" => { + MetaItem(NameValue(ref name, ref lit)) if name == "default" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { default.set(FieldDefault::Path(path)); } } // Parse `#[serde(skip_serializing)]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "skip_serializing" => { + MetaItem(Word(ref name)) if name == "skip_serializing" => { skip_serializing.set_true(); } // Parse `#[serde(skip_deserializing)]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) if name == "skip_deserializing" => { + MetaItem(Word(ref name)) if name == "skip_deserializing" => { skip_deserializing.set_true(); } // Parse `#[serde(skip_serializing_if="...")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { + MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { skip_serializing_if.set(path); } } // Parse `#[serde(serialize_with="...")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "serialize_with" => { + MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { serialize_with.set(path); } } // Parse `#[serde(deserialize_with="...")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "deserialize_with" => { + MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { deserialize_with.set(path); } } // Parse `#[serde(bound="D: Serialize")]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "bound" => { + MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { ser_bound.set(where_predicates.clone()); de_bound.set(where_predicates); @@ -353,19 +355,19 @@ impl Field { } // Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` - syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref name, ref meta_items)) if name == "bound" => { + MetaItem(List(ref name, ref meta_items)) if name == "bound" => { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { ser_bound.set_opt(ser); de_bound.set_opt(de); } } - syn::NestedMetaItem::MetaItem(ref meta_item) => { + MetaItem(ref meta_item) => { cx.error(format!("unknown serde field attribute `{}`", meta_item.name())); } - syn::NestedMetaItem::Literal(_) => { + Literal(_) => { cx.error(format!("unexpected literal in serde field attribute")); } } @@ -446,13 +448,13 @@ fn get_ser_and_de( for item in items { match *item { - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "serialize" => { + MetaItem(NameValue(ref name, ref lit)) if name == "serialize" => { if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) { ser_item.set(v); } } - syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref name, ref lit)) if name == "deserialize" => { + MetaItem(NameValue(ref name, ref lit)) if name == "deserialize" => { if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) { de_item.set(v); } @@ -485,7 +487,7 @@ fn get_where_predicates( pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> { match attr.value { - syn::MetaItem::List(ref name, ref items) if name == "serde" => { + List(ref name, ref items) if name == "serde" => { Some(items.iter().cloned().collect()) } _ => None From e7f3a80867adec89814120a73a477013ae6984c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 2 Nov 2016 22:58:55 -0700 Subject: [PATCH 081/111] Update serde codegen to syn 0.10 --- serde_codegen/Cargo.toml | 4 ++-- serde_codegen/src/lib.rs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index eb289be8..57f830dd 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,9 +22,9 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } -post-expansion = "0.1.0" +post-expansion = "0.2" quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } -syn = { version = "0.9", features = ["aster", "visit"] } +syn = { version = "0.10", features = ["aster", "visit"] } syntex = { version = "^0.48.0", optional = true } syntex_syntax = { version = "^0.48.0", optional = true } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index bad346dd..b9920af0 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -218,12 +218,14 @@ pub fn expand_single_item(item: &str) -> Result { }); } let rest: Vec<_> = nested.into_iter().filter(|nested| { + use syn::MetaItem::Word; + use syn::NestedMetaItem::MetaItem; match *nested { - syn::MetaItem::Word(ref word) if word == "Serialize" => { + MetaItem(Word(ref word)) if word == "Serialize" => { ser = true; false } - syn::MetaItem::Word(ref word) if word == "Deserialize" => { + MetaItem(Word(ref word)) if word == "Deserialize" => { de = true; false } From 133d117bf49b59a411eece18a29e0dc2efb34f8a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 7 Nov 2016 11:16:14 -0800 Subject: [PATCH 082/111] Bump post-expansion dependency --- serde_derive/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 5267b5d8..59157673 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies] -post-expansion = "0.1.0" +post-expansion = "0.2.0" [dependencies.serde_codegen] version = "=0.8.17" From a16f07858b130bd167968997e176dce9e8fa647e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 15 Nov 2016 21:29:34 -0500 Subject: [PATCH 083/111] Ask proc_macro_derive to ignore serde attributes --- serde_codegen/Cargo.toml | 1 - serde_codegen/src/lib.rs | 91 ++++++++-------------------------------- serde_derive/Cargo.toml | 3 -- serde_derive/src/lib.rs | 15 ++----- 4 files changed, 22 insertions(+), 88 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 57f830dd..60d73519 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,7 +22,6 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } -post-expansion = "0.2" quote = "0.3" serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index b9920af0..c2f7d1f2 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -27,9 +27,6 @@ extern crate syn; #[macro_use] extern crate quote; -#[cfg(feature = "with-syn")] -extern crate post_expansion; - #[cfg(feature = "with-syntex")] use std::path::Path; @@ -73,8 +70,8 @@ fn syntex_registry() -> syntex::Registry { reg.add_attr("feature(custom_derive)"); reg.add_attr("feature(custom_attribute)"); - reg.add_decorator("derive_Serialize", expand_derive_serialize); - reg.add_decorator("derive_Deserialize", expand_derive_deserialize); + reg.add_decorator("derive_Serialize", shim::expand_derive_serialize); + reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize); reg.add_post_expansion_pass(strip_attributes); @@ -112,19 +109,19 @@ pub fn register(reg: &mut rustc_plugin::Registry) { reg.register_syntax_extension( syntax::parse::token::intern("derive_Serialize"), syntax::ext::base::MultiDecorator( - Box::new(expand_derive_serialize))); + Box::new(shim::expand_derive_serialize))); reg.register_syntax_extension( syntax::parse::token::intern("derive_Deserialize"), syntax::ext::base::MultiDecorator( - Box::new(expand_derive_deserialize))); + Box::new(shim::expand_derive_deserialize))); reg.register_attribute("serde".to_owned(), AttributeType::Normal); } macro_rules! shim { ($name:ident $pkg:ident :: $func:ident) => { - fn $func( + pub fn $func( cx: &mut ::syntax::ext::base::ExtCtxt, span: ::syntax::codemap::Span, meta_item: &::syntax::ast::MetaItem, @@ -160,6 +157,7 @@ macro_rules! shim { use syntax::print::pprust; let s = pprust::item_to_string(item); + use {syn, $pkg}; let syn_item = syn::parse_macro_input(&s).unwrap(); let expanded = match $pkg::$func(&syn_item) { Ok(expanded) => expanded.to_string(), @@ -178,72 +176,19 @@ macro_rules! shim { }; } -shim!(Serialize ser::expand_derive_serialize); -shim!(Deserialize de::expand_derive_deserialize); +mod shim { + shim!(Serialize ser::expand_derive_serialize); + shim!(Deserialize de::expand_derive_deserialize); +} #[cfg(feature = "with-syn")] -pub fn expand_single_item(item: &str) -> Result { +pub fn expand_derive_serialize(item: &str) -> Result { let syn_item = syn::parse_macro_input(item).unwrap(); - let (ser, de, syn_item) = strip_serde_derives(syn_item); - let expanded_ser = if ser { - Some(try!(ser::expand_derive_serialize(&syn_item))) - } else { - None - }; - let expanded_de = if de { - Some(try!(de::expand_derive_deserialize(&syn_item))) - } else { - None - }; - let syn_item = post_expansion::strip_attrs_later(syn_item, &["serde"], "serde"); - return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string()); - - fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) { - let mut ser = false; - let mut de = false; - let item = syn::MacroInput { - attrs: item.attrs.into_iter().flat_map(|attr| { - if attr.is_sugared_doc || attr.style != syn::AttrStyle::Outer { - return Some(attr); - } - let (name, nested) = match attr.value { - syn::MetaItem::List(name, nested) => (name, nested), - _ => return Some(attr) - }; - if name != "derive" { - return Some(syn::Attribute { - style: syn::AttrStyle::Outer, - value: syn::MetaItem::List(name, nested), - is_sugared_doc: false, - }); - } - let rest: Vec<_> = nested.into_iter().filter(|nested| { - use syn::MetaItem::Word; - use syn::NestedMetaItem::MetaItem; - match *nested { - MetaItem(Word(ref word)) if word == "Serialize" => { - ser = true; - false - } - MetaItem(Word(ref word)) if word == "Deserialize" => { - de = true; - false - } - _ => true, - } - }).collect(); - if rest.is_empty() { - None - } else { - Some(syn::Attribute { - style: syn::AttrStyle::Outer, - value: syn::MetaItem::List(name, rest), - is_sugared_doc: false, - }) - } - }).collect(), - ..item - }; - (ser, de, item) - } + ser::expand_derive_serialize(&syn_item).map(|derive| derive.to_string()) +} + +#[cfg(feature = "with-syn")] +pub fn expand_derive_deserialize(item: &str) -> Result { + let syn_item = syn::parse_macro_input(item).unwrap(); + de::expand_derive_deserialize(&syn_item).map(|derive| derive.to_string()) } diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 59157673..3d3f4ae7 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -14,9 +14,6 @@ include = ["Cargo.toml", "src/**/*.rs"] name = "serde_derive" proc-macro = true -[dependencies] -post-expansion = "0.2.0" - [dependencies.serde_codegen] version = "=0.8.17" path = "../serde_codegen" diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index f631d6dd..cacc56e1 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -4,27 +4,20 @@ extern crate proc_macro; extern crate serde_codegen; -#[macro_use] -extern crate post_expansion; - use proc_macro::TokenStream; -#[proc_macro_derive(Serialize)] +#[proc_macro_derive(Serialize, attributes(serde))] pub fn derive_serialize(input: TokenStream) -> TokenStream { - let item = format!("#[derive(Serialize)]\n{}", input); - match serde_codegen::expand_single_item(&item) { + match serde_codegen::expand_derive_serialize(&input.to_string()) { Ok(expanded) => expanded.parse().unwrap(), Err(msg) => panic!(msg), } } -#[proc_macro_derive(Deserialize)] +#[proc_macro_derive(Deserialize, attributes(serde))] pub fn derive_deserialize(input: TokenStream) -> TokenStream { - let item = format!("#[derive(Deserialize)]\n{}", input); - match serde_codegen::expand_single_item(&item) { + match serde_codegen::expand_derive_deserialize(&input.to_string()) { Ok(expanded) => expanded.parse().unwrap(), Err(msg) => panic!(msg), } } - -register_post_expansion!(PostExpansion_serde); From 8b484c9703e9a61930175f8d682398eff9f217bd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 15 Nov 2016 21:37:19 -0500 Subject: [PATCH 084/111] Hide the serde_codegen functions from docs --- serde_codegen/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index c2f7d1f2..ba18584b 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -182,12 +182,16 @@ mod shim { } #[cfg(feature = "with-syn")] +#[doc(hidden)] +/// Not public API. Use the serde_derive crate. pub fn expand_derive_serialize(item: &str) -> Result { let syn_item = syn::parse_macro_input(item).unwrap(); ser::expand_derive_serialize(&syn_item).map(|derive| derive.to_string()) } #[cfg(feature = "with-syn")] +#[doc(hidden)] +/// Not public API. Use the serde_derive crate. pub fn expand_derive_deserialize(item: &str) -> Result { let syn_item = syn::parse_macro_input(item).unwrap(); de::expand_derive_deserialize(&syn_item).map(|derive| derive.to_string()) From 17fb4cb5032682311722fe8d20f02a9fa1ea58ba Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 19 Nov 2016 11:40:00 -0800 Subject: [PATCH 085/111] Release 0.8.18 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 8 ++++---- serde_codegen_internals/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 7d1db709..3c7154e1 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.17" +version = "0.8.18" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 60d73519..eee5e38a 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.17" +version = "0.8.18" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,7 +23,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } quote = "0.3" -serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" } +serde_codegen_internals = { version = "=0.11.0", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } -syntex = { version = "^0.48.0", optional = true } -syntex_syntax = { version = "^0.48.0", optional = true } +syntex = { version = "^0.50.0", optional = true } +syntex_syntax = { version = "^0.50.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 47e6504d..cf651684 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.10.0" +version = "0.11.0" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 3d3f4ae7..87969d2f 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.17" +version = "0.8.18" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.17" +version = "=0.8.18" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.17", path = "../serde" } -serde_test = { version = "0.8.17", path = "../serde_test" } +serde = { version = "0.8.18", path = "../serde" } +serde_test = { version = "0.8.18", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 387c2577..f4cde744 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.17" +version = "0.8.18" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.17", path = "../serde" } +serde = { version = "0.8.18", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index daf56fe7..c045a827 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.17" +version = "0.8.18" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 8dba87661b4fe01ddd1161e605c047cb3da2e721 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 19 Nov 2016 11:47:19 -0800 Subject: [PATCH 086/111] Bump serde_codegen_internals because it failed to publish somehow --- serde_codegen/Cargo.toml | 2 +- serde_codegen_internals/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index eee5e38a..48a2c5e1 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -23,7 +23,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } quote = "0.3" -serde_codegen_internals = { version = "=0.11.0", default-features = false, path = "../serde_codegen_internals" } +serde_codegen_internals = { version = "=0.11.1", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } syntex = { version = "^0.50.0", optional = true } syntex_syntax = { version = "^0.50.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index cf651684..69488557 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.11.0" +version = "0.11.1" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." From 7efa0153b0371cbf0b456bd6660161a2aeab74a2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 19 Nov 2016 15:24:40 -0800 Subject: [PATCH 087/111] Drop testing on rust 1.10 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index be03184b..0bf5d22d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ sudo: false language: rust rust: -- 1.10.0 - 1.11.0 +- 1.12.0 - stable - beta - nightly From 6eca34c45ce0ce71d576d5f0c0dce0593f32fe61 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 23 Nov 2016 09:13:21 -0800 Subject: [PATCH 088/111] Drop libsyntax --- serde_codegen/src/lib.rs | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index ba18584b..1b2e18c5 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -2,7 +2,6 @@ #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", allow(too_many_arguments))] #![cfg_attr(feature = "clippy", allow(used_underscore_binding))] -#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))] // The `quote!` macro requires deep recursion. #![recursion_limit = "192"] @@ -16,13 +15,6 @@ extern crate syntex; #[macro_use] extern crate syntex_syntax as syntax; -#[cfg(not(feature = "with-syntex"))] -#[macro_use] -extern crate syntax; - -#[cfg(not(feature = "with-syntex"))] -extern crate rustc_plugin; - extern crate syn; #[macro_use] extern crate quote; @@ -30,9 +22,6 @@ extern crate quote; #[cfg(feature = "with-syntex")] use std::path::Path; -#[cfg(not(feature = "with-syntex"))] -use syntax::feature_gate::AttributeType; - mod bound; mod de; mod ser; @@ -104,21 +93,6 @@ pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> syntex::with_extra_stack(expand_thread) } -#[cfg(not(feature = "with-syntex"))] -pub fn register(reg: &mut rustc_plugin::Registry) { - reg.register_syntax_extension( - syntax::parse::token::intern("derive_Serialize"), - syntax::ext::base::MultiDecorator( - Box::new(shim::expand_derive_serialize))); - - reg.register_syntax_extension( - syntax::parse::token::intern("derive_Deserialize"), - syntax::ext::base::MultiDecorator( - Box::new(shim::expand_derive_deserialize))); - - reg.register_attribute("serde".to_owned(), AttributeType::Normal); -} - macro_rules! shim { ($name:ident $pkg:ident :: $func:ident) => { pub fn $func( @@ -176,6 +150,7 @@ macro_rules! shim { }; } +#[cfg(feature = "with-syntex")] mod shim { shim!(Serialize ser::expand_derive_serialize); shim!(Deserialize de::expand_derive_deserialize); From 36641e7b8139fb302f8799d54fd866b84889a2bb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 23 Nov 2016 09:14:03 -0800 Subject: [PATCH 089/111] Release 0.8.19 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 3c7154e1..7fe2c880 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.18" +version = "0.8.19" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 48a2c5e1..b28ae608 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.18" +version = "0.8.19" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 87969d2f..a277c0d4 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.18" +version = "0.8.19" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.18" +version = "=0.8.19" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.18", path = "../serde" } -serde_test = { version = "0.8.18", path = "../serde_test" } +serde = { version = "0.8.19", path = "../serde" } +serde_test = { version = "0.8.19", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index f4cde744..95c2bef9 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.18" +version = "0.8.19" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.18", path = "../serde" } +serde = { version = "0.8.19", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index c045a827..7490835e 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.18" +version = "0.8.19" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 5bda95ba813b3512baa501a9005c956d8718604a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 24 Nov 2016 12:57:31 -0800 Subject: [PATCH 090/111] Do not copy tokens to String after expanding --- serde_codegen/Cargo.toml | 2 +- serde_codegen/src/lib.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index b28ae608..8f0b272f 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -22,7 +22,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } -quote = "0.3" +quote = "0.3.8" serde_codegen_internals = { version = "=0.11.1", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } syntex = { version = "^0.50.0", optional = true } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 1b2e18c5..a2afd7bd 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -159,15 +159,15 @@ mod shim { #[cfg(feature = "with-syn")] #[doc(hidden)] /// Not public API. Use the serde_derive crate. -pub fn expand_derive_serialize(item: &str) -> Result { +pub fn expand_derive_serialize(item: &str) -> Result { let syn_item = syn::parse_macro_input(item).unwrap(); - ser::expand_derive_serialize(&syn_item).map(|derive| derive.to_string()) + ser::expand_derive_serialize(&syn_item) } #[cfg(feature = "with-syn")] #[doc(hidden)] /// Not public API. Use the serde_derive crate. -pub fn expand_derive_deserialize(item: &str) -> Result { +pub fn expand_derive_deserialize(item: &str) -> Result { let syn_item = syn::parse_macro_input(item).unwrap(); - de::expand_derive_deserialize(&syn_item).map(|derive| derive.to_string()) + de::expand_derive_deserialize(&syn_item) } From d63d09f4db4132d9eacad8e95d2370f393aef288 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 1 Dec 2016 11:23:12 +0100 Subject: [PATCH 091/111] Enable deserializing an empty `String` from a unit value --- serde/src/de/impls.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 915ef5b2..8cad930a 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -283,6 +283,12 @@ impl Visitor for StringVisitor { Ok(v) } + fn visit_unit(&mut self) -> Result + where E: Error, + { + Ok(String::new()) + } + fn visit_bytes(&mut self, v: &[u8]) -> Result where E: Error, { From 5e47c87ba0f0a44d4d632331246e64251946e3c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 1 Dec 2016 04:46:24 -0800 Subject: [PATCH 092/111] Add test for deserializing unit to string --- testing/tests/test_de.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/tests/test_de.rs b/testing/tests/test_de.rs index 162bf016..56fb1cee 100644 --- a/testing/tests/test_de.rs +++ b/testing/tests/test_de.rs @@ -215,6 +215,9 @@ declare_tests! { Token::SeqEnd, ], } + test_unit_string { + String::new() => &[Token::Unit], + } test_tuple_struct { TupleStruct(1, 2, 3) => &[ Token::SeqStart(Some(3)), From 95ffca9bbea27b7fae4893991f7ff1d80722ecaf Mon Sep 17 00:00:00 2001 From: Shing Lyu Date: Thu, 15 Dec 2016 22:23:52 +0800 Subject: [PATCH 093/111] Implemented skip_deserializing for enum --- serde_codegen/src/de.rs | 3 ++- serde_codegen_internals/src/attr.rs | 11 +++++++++++ testing/tests/test_de.rs | 10 +++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index 93d7d6cf..877b6a05 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -496,6 +496,7 @@ fn deserialize_item_enum( let variant_visitor = deserialize_field_visitor( variants.iter() + .filter(|variant| !variant.attrs.skip_deserializing()) .map(|variant| variant.attrs.name().deserialize_name()) .collect(), item_attrs, @@ -518,7 +519,7 @@ fn deserialize_item_enum( // Match arms to extract a variant from a string let mut variant_arms = vec![]; - for (i, variant) in variants.iter().enumerate() { + for (i, variant) in variants.iter().filter(|variant| !variant.attrs.skip_deserializing()).enumerate() { let variant_name = aster::id(format!("__field{}", i)); let variant_name = quote!(__Field::#variant_name); diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 124592dc..a9a69169 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -187,12 +187,14 @@ impl Item { #[derive(Debug)] pub struct Variant { name: Name, + skip_deserializing: bool, } impl Variant { pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); + let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { @@ -212,6 +214,10 @@ impl Variant { de_name.set_opt(de); } } + // Parse `#[serde(skip_deserializing)]` + MetaItem(Word(ref name)) if name == "skip_deserializing" => { + skip_deserializing.set_true(); + } MetaItem(ref meta_item) => { cx.error(format!("unknown serde variant attribute `{}`", @@ -230,12 +236,17 @@ impl Variant { serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()), deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()), }, + skip_deserializing: skip_deserializing.get(), } } pub fn name(&self) -> &Name { &self.name } + + pub fn skip_deserializing(&self) -> bool { + self.skip_deserializing + } } /// Represents field attribute information diff --git a/testing/tests/test_de.rs b/testing/tests/test_de.rs index 56fb1cee..e929d3a1 100644 --- a/testing/tests/test_de.rs +++ b/testing/tests/test_de.rs @@ -37,7 +37,9 @@ enum Enum { Unit, Simple(i32), Seq(i32, i32, i32), - Map { a: i32, b: i32, c: i32 } + Map { a: i32, b: i32, c: i32 }, + #[serde(skip_deserializing)] + Skipped, } ////////////////////////////////////////////////////////////////////////// @@ -805,6 +807,12 @@ declare_error_tests! { ], Error::UnknownVariant("Foo".to_owned()), } + test_enum_skipped_variant { + &[ + Token::EnumUnit("Enum", "Skipped"), + ], + Error::UnknownVariant("Skipped".to_owned()), + } test_struct_seq_too_long { &[ Token::SeqStart(Some(4)), From 08c59a2e0e89434d259e9f59b326cbeb96af0034 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 16 Dec 2016 07:55:43 -0800 Subject: [PATCH 094/111] Release 0.8.20 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 4 ++-- serde_codegen_internals/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 7fe2c880..699a0f7f 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.19" +version = "0.8.20" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 8f0b272f..0ac76364 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.19" +version = "0.8.20" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,7 +23,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } quote = "0.3.8" -serde_codegen_internals = { version = "=0.11.1", default-features = false, path = "../serde_codegen_internals" } +serde_codegen_internals = { version = "=0.11.2", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } syntex = { version = "^0.50.0", optional = true } syntex_syntax = { version = "^0.50.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 69488557..820238fd 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.11.1" +version = "0.11.2" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index a277c0d4..e59cc140 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.19" +version = "0.8.20" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.19" +version = "=0.8.20" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.19", path = "../serde" } -serde_test = { version = "0.8.19", path = "../serde_test" } +serde = { version = "0.8.20", path = "../serde" } +serde_test = { version = "0.8.20", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 95c2bef9..bc039852 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.19" +version = "0.8.20" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.19", path = "../serde" } +serde = { version = "0.8.20", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 7490835e..52d9bfd6 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.19" +version = "0.8.20" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From 7222cf7514afdb7e19043db7ee7a2e001a574b5c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 17 Dec 2016 17:31:11 -0800 Subject: [PATCH 095/111] Ignore warning from unused enum variant --- testing/tests/test_de.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/tests/test_de.rs b/testing/tests/test_de.rs index e929d3a1..280d427f 100644 --- a/testing/tests/test_de.rs +++ b/testing/tests/test_de.rs @@ -38,6 +38,7 @@ enum Enum { Simple(i32), Seq(i32, i32, i32), Map { a: i32, b: i32, c: i32 }, + #[allow(dead_code)] #[serde(skip_deserializing)] Skipped, } From 36f07912b87ad4510d377b6bd799359349ce303d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 17 Dec 2016 17:32:04 -0800 Subject: [PATCH 096/111] Remove no-longer-necessary cfg This was fixed in Rust, allowing proc macro crates to be tested. --- serde_derive/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index cacc56e1..c625404e 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,5 +1,4 @@ #![feature(proc_macro, proc_macro_lib)] -#![cfg(not(test))] extern crate proc_macro; extern crate serde_codegen; From 2c984980a0faf0670d1d461aac2527feecf9de30 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 22 Dec 2016 21:52:37 -0500 Subject: [PATCH 097/111] Link to release notes from readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f0c6ec64..9f480b18 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ You may be looking for: - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html) - [Examples](https://serde.rs/examples.html) - [API documentation](https://docs.serde.rs/serde/) +- [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action From 871fb5adee212a4e65c813a3d99748ae27eb168f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 23 Dec 2016 23:17:42 -0500 Subject: [PATCH 098/111] Support deserializing ByteBuf from string --- serde/src/bytes.rs | 14 ++- testing/tests/test.rs.in | 1 + testing/tests/test_bytes.rs | 195 ++++++++---------------------------- 3 files changed, 54 insertions(+), 156 deletions(-) diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs index a732712c..db98f2d8 100644 --- a/serde/src/bytes.rs +++ b/serde/src/bytes.rs @@ -208,7 +208,7 @@ mod bytebuf { fn visit_bytes(&mut self, v: &[u8]) -> Result where E: de::Error, { - self.visit_byte_buf(v.to_vec()) + Ok(ByteBuf::from(v)) } #[inline] @@ -217,6 +217,18 @@ mod bytebuf { { Ok(ByteBuf::from(v)) } + + fn visit_str(&mut self, v: &str) -> Result + where E: de::Error, + { + Ok(ByteBuf::from(v)) + } + + fn visit_string(&mut self, v: String) -> Result + where E: de::Error, + { + Ok(ByteBuf::from(v)) + } } impl de::Deserialize for ByteBuf { diff --git a/testing/tests/test.rs.in b/testing/tests/test.rs.in index fca1ff46..04c69bdb 100644 --- a/testing/tests/test.rs.in +++ b/testing/tests/test.rs.in @@ -1,4 +1,5 @@ extern crate serde; +extern crate serde_test; #[macro_use] mod macros; diff --git a/testing/tests/test_bytes.rs b/testing/tests/test_bytes.rs index fd707e21..a0e5fbcc 100644 --- a/testing/tests/test_bytes.rs +++ b/testing/tests/test_bytes.rs @@ -1,11 +1,13 @@ use std::fmt; use std::error; -use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use serde::{Serialize, Serializer}; use serde::bytes::{ByteBuf, Bytes}; use serde::ser; use serde::de; +use serde_test::{assert_de_tokens, Token}; + /////////////////////////////////////////////////////////////////////////////// #[derive(Debug, PartialEq)] @@ -286,153 +288,6 @@ impl Serializer for BytesSerializer { /////////////////////////////////////////////////////////////////////////////// -struct BytesDeserializer { - bytes: Option>, -} - -impl BytesDeserializer { - fn new(bytes: Vec) -> Self { - BytesDeserializer { - bytes: Some(bytes), - } - } -} - -impl Deserializer for BytesDeserializer { - type Error = Error; - - fn deserialize(&mut self, _visitor: V) -> Result - where V: de::Visitor, - { - Err(Error) - } - - fn deserialize_bytes(&mut self, mut visitor: V) -> Result - where V: de::Visitor, - { - visitor.visit_byte_buf(self.bytes.take().unwrap()) - } - - fn deserialize_seq<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_struct_field<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_map<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_unit<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_ignored_any<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_string<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_str<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_char<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_i64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_i32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_i16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_i8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_u64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_u32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_u16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_u8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_f32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_f64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_bool<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_usize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_isize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error> - where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_option<__V>(&mut self, visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_seq_fixed_size<__V>(&mut self, _: usize, visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_unit_struct<__V>(&mut self, _: &str, visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_newtype_struct<__V>(&mut self, _: &str, visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_tuple_struct<__V>(&mut self, _: &str, _: usize, visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_struct<__V>(&mut self, _: &str, _: &[&str], visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_tuple<__V>(&mut self, _: usize, visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::Visitor { - self.deserialize(visitor) - } - fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _visitor: __V) - -> Result<__V::Value, Self::Error> where __V: de::EnumVisitor { - Err(Error) - } -} - -/////////////////////////////////////////////////////////////////////////////// - #[test] fn test_bytes_ser_bytes() { let buf = vec![]; @@ -449,12 +304,42 @@ fn test_bytes_ser_bytes() { /////////////////////////////////////////////////////////////////////////////// #[test] -fn test_byte_buf_de_bytes() { - let mut de = BytesDeserializer::new(vec![]); - let bytes = Deserialize::deserialize(&mut de); - assert_eq!(bytes, Ok(ByteBuf::new())); +fn test_byte_buf_de() { + let empty = ByteBuf::new(); + assert_de_tokens(&empty, &[Token::Bytes(b""),]); + assert_de_tokens(&empty, &[Token::Str("")]); + assert_de_tokens(&empty, &[Token::String(String::new())]); + assert_de_tokens(&empty, &[ + Token::SeqStart(None), + Token::SeqEnd, + ]); + assert_de_tokens(&empty, &[ + Token::SeqStart(Some(0)), + Token::SeqEnd, + ]); - let mut de = BytesDeserializer::new(vec![1, 2, 3]); - let bytes = Deserialize::deserialize(&mut de); - assert_eq!(bytes, Ok(ByteBuf::from(vec![1, 2, 3]))); + let buf = ByteBuf::from(vec![65, 66, 67]); + assert_de_tokens(&buf, &[Token::Bytes(b"ABC")]); + assert_de_tokens(&buf, &[Token::Str("ABC")]); + assert_de_tokens(&buf, &[Token::String("ABC".to_owned())]); + assert_de_tokens(&buf, &[ + Token::SeqStart(None), + Token::SeqSep, + Token::U8(65), + Token::SeqSep, + Token::U8(66), + Token::SeqSep, + Token::U8(67), + Token::SeqEnd, + ]); + assert_de_tokens(&buf, &[ + Token::SeqStart(Some(3)), + Token::SeqSep, + Token::U8(65), + Token::SeqSep, + Token::U8(66), + Token::SeqSep, + Token::U8(67), + Token::SeqEnd, + ]); } From b7ea21392614a4238dc29e48833c4498d4a67e50 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 23 Dec 2016 23:30:27 -0500 Subject: [PATCH 099/111] Support nostd for ByteBuf from String --- serde/src/bytes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serde/src/bytes.rs b/serde/src/bytes.rs index db98f2d8..988c24a5 100644 --- a/serde/src/bytes.rs +++ b/serde/src/bytes.rs @@ -84,7 +84,7 @@ mod bytebuf { use de; #[cfg(feature = "collections")] - use collections::Vec; + use collections::{String, Vec}; /// `ByteBuf` wraps a `Vec` and serializes as a byte array. #[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] From 2fea8c9c287e18e685493c78979ca9b5e86c35c8 Mon Sep 17 00:00:00 2001 From: Shing Lyu Date: Sat, 24 Dec 2016 14:37:23 +0800 Subject: [PATCH 100/111] Implement skip_serializing for enum variant --- serde_codegen/src/ser.rs | 170 ++++++++++++++++++---------- serde_codegen_internals/src/attr.rs | 11 ++ testing/tests/test_ser.rs | 30 ++++- 3 files changed, 148 insertions(+), 63 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 449a2490..53160416 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -255,77 +255,123 @@ fn serialize_variant( let variant_ident = variant.ident.clone(); let variant_name = variant.attrs.name().serialize_name(); + let skipped_err = quote! { + Err(_serde::ser::Error::invalid_value("The enum variant was skipped for serialization")) + }; - match variant.style { - Style::Unit => { - quote! { - #type_ident::#variant_ident => - _serde::ser::Serializer::serialize_unit_variant( - _serializer, - #type_name, - #variant_index, - #variant_name, - ), - } - }, - Style::Newtype => { - let block = serialize_newtype_variant( - type_name, - variant_index, - variant_name, - ty, - generics, - &variant.fields[0], - ); + if variant.attrs.skip_serializing() { + match variant.style { + Style::Unit => { + quote! { + #type_ident::#variant_ident => #skipped_err, + } + }, + Style::Newtype => { + quote! { + #type_ident::#variant_ident(ref __simple_value) => #skipped_err, + } + }, + Style::Tuple => { + let field_names: Vec = (0 .. variant.fields.len()) + .map(|i| { + let id = aster::id(format!("__field{}", i)); + quote!(ref #id) + }) + .collect(); - quote! { - #type_ident::#variant_ident(ref __simple_value) => #block, + let pat = quote!(#type_ident::#variant_ident(#(#field_names),*)); + + quote! { + #pat => #skipped_err, + } } - }, - Style::Tuple => { - let field_names: Vec = (0 .. variant.fields.len()) - .map(|i| { - let id = aster::id(format!("__field{}", i)); + Style::Struct => { + let fields = variant.fields.iter().map(|field| { + let id = match field.ident { + Some(ref name) => name.clone(), + None => panic!("struct variant has unnamed fields"), + }; quote!(ref #id) - }) - .collect(); + }); + let pat = quote!(#type_ident::#variant_ident { #(#fields),* }); - let pat = quote!(#type_ident::#variant_ident(#(#field_names),*)); - - let block = serialize_tuple_variant( - type_name, - variant_index, - variant_name, - generics, - ty, - &variant.fields, - ); - - quote! { - #pat => { #block } + quote! { + #pat => #skipped_err, + } } } - Style::Struct => { - let fields = variant.fields.iter().map(|field| { - let id = match field.ident { - Some(ref name) => name.clone(), - None => panic!("struct variant has unnamed fields"), - }; - quote!(ref #id) - }); - let pat = quote!(#type_ident::#variant_ident { #(#fields),* }); + } else { // variant wasn't skipped + match variant.style { + Style::Unit => { + quote! { + #type_ident::#variant_ident => + _serde::ser::Serializer::serialize_unit_variant( + _serializer, + #type_name, + #variant_index, + #variant_name, + ), + } + }, + Style::Newtype => { + let block = serialize_newtype_variant( + type_name, + variant_index, + variant_name, + ty, + generics, + &variant.fields[0], + ); - let block = serialize_struct_variant( - variant_index, - variant_name, - generics, - ty, - &variant.fields, - item_attrs, - ); + quote! { + #type_ident::#variant_ident(ref __simple_value) => #block, + } + }, + Style::Tuple => { + let field_names: Vec = (0 .. variant.fields.len()) + .map(|i| { + let id = aster::id(format!("__field{}", i)); + quote!(ref #id) + }) + .collect(); - quote! { - #pat => { #block } + let pat = quote!(#type_ident::#variant_ident(#(#field_names),*)); + + let block = serialize_tuple_variant( + type_name, + variant_index, + variant_name, + generics, + ty, + &variant.fields, + ); + + quote! { + #pat => { #block } + } + } + Style::Struct => { + let fields = variant.fields.iter().map(|field| { + let id = match field.ident { + Some(ref name) => name.clone(), + None => panic!("struct variant has unnamed fields"), + }; + quote!(ref #id) + }); + let pat = quote!(#type_ident::#variant_ident { #(#fields),* }); + + let block = serialize_struct_variant( + variant_index, + variant_name, + generics, + ty, + &variant.fields, + item_attrs, + ); + + quote! { + #pat => { #block } + } } } } diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index a9a69169..632dd508 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -188,6 +188,7 @@ impl Item { pub struct Variant { name: Name, skip_deserializing: bool, + skip_serializing: bool, } impl Variant { @@ -195,6 +196,7 @@ impl Variant { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); + let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { @@ -218,6 +220,10 @@ impl Variant { MetaItem(Word(ref name)) if name == "skip_deserializing" => { skip_deserializing.set_true(); } + // Parse `#[serde(skip_serializing)]` + MetaItem(Word(ref name)) if name == "skip_serializing" => { + skip_serializing.set_true(); + } MetaItem(ref meta_item) => { cx.error(format!("unknown serde variant attribute `{}`", @@ -237,6 +243,7 @@ impl Variant { deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()), }, skip_deserializing: skip_deserializing.get(), + skip_serializing: skip_serializing.get(), } } @@ -247,6 +254,10 @@ impl Variant { pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } + + pub fn skip_serializing(&self) -> bool { + self.skip_serializing + } } /// Represents field attribute information diff --git a/testing/tests/test_ser.rs b/testing/tests/test_ser.rs index 52573533..afc85070 100644 --- a/testing/tests/test_ser.rs +++ b/testing/tests/test_ser.rs @@ -30,12 +30,20 @@ struct Struct { c: i32, } -#[derive(Serialize)] +#[derive(Serialize, PartialEq, Debug)] enum Enum { Unit, One(i32), Seq(i32, i32), Map { a: i32, b: i32 }, + #[serde(skip_serializing)] + SkippedUnit, + #[serde(skip_serializing)] + SkippedOne(i32), + #[serde(skip_serializing)] + SkippedSeq(i32, i32), + #[serde(skip_serializing)] + SkippedMap { _a: i32, _b: i32 }, } ////////////////////////////////////////////////////////////////////////// @@ -388,3 +396,23 @@ fn test_cannot_serialize_paths() { &[], Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned())); } + +#[test] +fn test_enum_skipped() { + assert_ser_tokens_error( + &Enum::SkippedUnit, + &[], + Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + assert_ser_tokens_error( + &Enum::SkippedOne(42), + &[], + Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + assert_ser_tokens_error( + &Enum::SkippedSeq(1, 2), + &[], + Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + assert_ser_tokens_error( + &Enum::SkippedMap { _a: 1, _b: 2 }, + &[], + Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); +} From 49e985eb9099f244e8081e00601c409ffed5aef4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Dec 2016 12:16:28 -0500 Subject: [PATCH 101/111] Update message for skipped enum variant --- serde_codegen/src/ser.rs | 5 ++++- testing/tests/test_ser.rs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 53160416..0fc928af 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -255,8 +255,11 @@ fn serialize_variant( let variant_ident = variant.ident.clone(); let variant_name = variant.attrs.name().serialize_name(); + + let skipped_msg = format!("The enum variant {}::{} cannot be serialized", + type_ident, variant_ident); let skipped_err = quote! { - Err(_serde::ser::Error::invalid_value("The enum variant was skipped for serialization")) + Err(_serde::ser::Error::invalid_value(#skipped_msg)) }; if variant.attrs.skip_serializing() { diff --git a/testing/tests/test_ser.rs b/testing/tests/test_ser.rs index afc85070..3a5a5748 100644 --- a/testing/tests/test_ser.rs +++ b/testing/tests/test_ser.rs @@ -402,17 +402,17 @@ fn test_enum_skipped() { assert_ser_tokens_error( &Enum::SkippedUnit, &[], - Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + Error::InvalidValue("The enum variant Enum::SkippedUnit cannot be serialized".to_owned())); assert_ser_tokens_error( &Enum::SkippedOne(42), &[], - Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + Error::InvalidValue("The enum variant Enum::SkippedOne cannot be serialized".to_owned())); assert_ser_tokens_error( &Enum::SkippedSeq(1, 2), &[], - Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + Error::InvalidValue("The enum variant Enum::SkippedSeq cannot be serialized".to_owned())); assert_ser_tokens_error( &Enum::SkippedMap { _a: 1, _b: 2 }, &[], - Error::InvalidValue("The enum variant was skipped for serialization".to_owned())); + Error::InvalidValue("The enum variant Enum::SkippedMap cannot be serialized".to_owned())); } From a020cceed8f6ef970d906de193b657f92ae2b069 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Dec 2016 12:18:02 -0500 Subject: [PATCH 102/111] Simplify variant serialize patterns --- serde_codegen/src/ser.rs | 38 ++++++-------------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 0fc928af..c4dbc395 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -266,40 +266,17 @@ fn serialize_variant( match variant.style { Style::Unit => { quote! { - #type_ident::#variant_ident => #skipped_err, + #type_ident::#variant_ident => #skipped_err, } }, - Style::Newtype => { + Style::Newtype | Style::Tuple => { quote! { - #type_ident::#variant_ident(ref __simple_value) => #skipped_err, + #type_ident::#variant_ident(..) => #skipped_err, } }, - Style::Tuple => { - let field_names: Vec = (0 .. variant.fields.len()) - .map(|i| { - let id = aster::id(format!("__field{}", i)); - quote!(ref #id) - }) - .collect(); - - let pat = quote!(#type_ident::#variant_ident(#(#field_names),*)); - - quote! { - #pat => #skipped_err, - } - } Style::Struct => { - let fields = variant.fields.iter().map(|field| { - let id = match field.ident { - Some(ref name) => name.clone(), - None => panic!("struct variant has unnamed fields"), - }; - quote!(ref #id) - }); - let pat = quote!(#type_ident::#variant_ident { #(#fields),* }); - quote! { - #pat => #skipped_err, + #type_ident::#variant_ident{..} => #skipped_err, } } } @@ -338,8 +315,6 @@ fn serialize_variant( }) .collect(); - let pat = quote!(#type_ident::#variant_ident(#(#field_names),*)); - let block = serialize_tuple_variant( type_name, variant_index, @@ -350,7 +325,7 @@ fn serialize_variant( ); quote! { - #pat => { #block } + #type_ident::#variant_ident(#(#field_names),*) => { #block } } } Style::Struct => { @@ -361,7 +336,6 @@ fn serialize_variant( }; quote!(ref #id) }); - let pat = quote!(#type_ident::#variant_ident { #(#fields),* }); let block = serialize_struct_variant( variant_index, @@ -373,7 +347,7 @@ fn serialize_variant( ); quote! { - #pat => { #block } + #type_ident::#variant_ident { #(#fields),* } => { #block } } } } From 57d3fce0c6a765ae0fa75db82b9a8444e003c97a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Dec 2016 12:26:02 -0500 Subject: [PATCH 103/111] Further simplify variant serialization patterns --- serde_codegen/src/ser.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index c4dbc395..e9eb38f4 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -308,12 +308,8 @@ fn serialize_variant( } }, Style::Tuple => { - let field_names: Vec = (0 .. variant.fields.len()) - .map(|i| { - let id = aster::id(format!("__field{}", i)); - quote!(ref #id) - }) - .collect(); + let field_names = (0 .. variant.fields.len()) + .map(|i| aster::id(format!("__field{}", i))); let block = serialize_tuple_variant( type_name, @@ -325,17 +321,12 @@ fn serialize_variant( ); quote! { - #type_ident::#variant_ident(#(#field_names),*) => { #block } + #type_ident::#variant_ident(#(ref #field_names),*) => { #block } } } Style::Struct => { - let fields = variant.fields.iter().map(|field| { - let id = match field.ident { - Some(ref name) => name.clone(), - None => panic!("struct variant has unnamed fields"), - }; - quote!(ref #id) - }); + let fields = variant.fields.iter() + .map(|f| f.ident.clone().expect("struct variant has unnamed fields")); let block = serialize_struct_variant( variant_index, @@ -347,7 +338,7 @@ fn serialize_variant( ); quote! { - #type_ident::#variant_ident { #(#fields),* } => { #block } + #type_ident::#variant_ident { #(ref #fields),* } => { #block } } } } From 2401ae61a8f3363bb5471fe183487720794d510e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Dec 2016 12:42:23 -0500 Subject: [PATCH 104/111] Update to syntex 0.52 --- serde_codegen/Cargo.toml | 4 ++-- serde_codegen/src/lib.rs | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 0ac76364..0c53dd7f 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -25,5 +25,5 @@ clippy = { version = "^0.*", optional = true } quote = "0.3.8" serde_codegen_internals = { version = "=0.11.2", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } -syntex = { version = "^0.50.0", optional = true } -syntex_syntax = { version = "^0.50.0", optional = true } +syntex = { version = "^0.52.0", optional = true } +syntex_syntax = { version = "^0.52.0", optional = true } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index a2afd7bd..797082b7 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -38,11 +38,11 @@ fn syntex_registry() -> syntex::Registry { impl fold::Folder for StripAttributeFolder { fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { - match attr.node.value.node { - ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; } - _ => {} + if attr.value.name == "serde" { + if let ast::MetaItemKind::List(..) = attr.value.node { + return None; + } } - Some(attr) } @@ -118,11 +118,10 @@ macro_rules! shim { struct MarkSerdeAttributesUsed; impl visit::Visitor for MarkSerdeAttributesUsed { fn visit_attribute(&mut self, attr: &ast::Attribute) { - match attr.node.value.node { - ast::MetaItemKind::List(ref name, _) if name == "serde" => { + if attr.value.name == "serde" { + if let ast::MetaItemKind::List(..) = attr.value.node { attr::mark_used(attr); } - _ => {} } } } From 28d67f4172268c8e9b6a291d8338afda41163249 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Dec 2016 13:10:06 -0500 Subject: [PATCH 105/111] Format variant-skip message only if variant is skipped --- serde_codegen/src/ser.rs | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index e9eb38f4..65459abc 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -256,29 +256,19 @@ fn serialize_variant( let variant_ident = variant.ident.clone(); let variant_name = variant.attrs.name().serialize_name(); - let skipped_msg = format!("The enum variant {}::{} cannot be serialized", - type_ident, variant_ident); - let skipped_err = quote! { - Err(_serde::ser::Error::invalid_value(#skipped_msg)) - }; - if variant.attrs.skip_serializing() { - match variant.style { - Style::Unit => { - quote! { - #type_ident::#variant_ident => #skipped_err, - } - }, - Style::Newtype | Style::Tuple => { - quote! { - #type_ident::#variant_ident(..) => #skipped_err, - } - }, - Style::Struct => { - quote! { - #type_ident::#variant_ident{..} => #skipped_err, - } - } + let skipped_msg = format!("The enum variant {}::{} cannot be serialized", + type_ident, variant_ident); + let skipped_err = quote! { + Err(_serde::ser::Error::invalid_value(#skipped_msg)) + }; + let fields_pat = match variant.style { + Style::Unit => quote!(), + Style::Newtype | Style::Tuple => quote!( (..) ), + Style::Struct => quote!( {..} ), + }; + quote! { + #type_ident::#variant_ident #fields_pat => #skipped_err, } } else { // variant wasn't skipped match variant.style { From 9338c4f1b94d54e04c769c2792c11c03ffe7fad0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Dec 2016 12:36:54 -0500 Subject: [PATCH 106/111] Release 0.8.21 --- serde/Cargo.toml | 2 +- serde_codegen/Cargo.toml | 4 ++-- serde_codegen_internals/Cargo.toml | 2 +- serde_derive/Cargo.toml | 8 ++++---- serde_test/Cargo.toml | 4 ++-- testing/Cargo.toml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index 699a0f7f..c33ff331 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde" -version = "0.8.20" +version = "0.8.21" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 0c53dd7f..4217841d 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen" -version = "0.8.20" +version = "0.8.21" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros to auto-generate implementations for the serde framework" @@ -23,7 +23,7 @@ with-syn = [] [dependencies] clippy = { version = "^0.*", optional = true } quote = "0.3.8" -serde_codegen_internals = { version = "=0.11.2", default-features = false, path = "../serde_codegen_internals" } +serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } syntex = { version = "^0.52.0", optional = true } syntex_syntax = { version = "^0.52.0", optional = true } diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index 820238fd..f03cacd8 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_codegen_internals" -version = "0.11.2" +version = "0.11.3" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "AST representation used by Serde codegen. Unstable." diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index e59cc140..053732e0 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_derive" -version = "0.8.20" +version = "0.8.21" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" @@ -15,7 +15,7 @@ name = "serde_derive" proc-macro = true [dependencies.serde_codegen] -version = "=0.8.20" +version = "=0.8.21" path = "../serde_codegen" default-features = false features = ["with-syn"] @@ -23,5 +23,5 @@ features = ["with-syn"] [dev-dependencies] compiletest_rs = "^0.2.0" fnv = "1.0" -serde = { version = "0.8.20", path = "../serde" } -serde_test = { version = "0.8.20", path = "../serde_test" } +serde = { version = "0.8.21", path = "../serde" } +serde_test = { version = "0.8.21", path = "../serde_test" } diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index bc039852..5e39bbce 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_test" -version = "0.8.20" +version = "0.8.21" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "Token De/Serializer for testing De/Serialize implementations" @@ -12,4 +12,4 @@ keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] [dependencies] -serde = { version = "0.8.20", path = "../serde" } +serde = { version = "0.8.21", path = "../serde" } diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 52d9bfd6..6c19d8d1 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_testing" -version = "0.8.20" +version = "0.8.21" authors = ["Erick Tryzelaar "] license = "MIT/Apache-2.0" description = "A generic serialization/deserialization framework" From b6e8b58cb2a6d42f1521513ef9cd06bb0f6dbd32 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 2 Jan 2017 14:59:00 -0800 Subject: [PATCH 107/111] Stop testing on 1.11 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0bf5d22d..87e33f84 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ sudo: false language: rust rust: -- 1.11.0 - 1.12.0 +- 1.13.0 - stable - beta - nightly From 1ecf3730ee459282914e31faaf0f041473c4bca9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 6 Jan 2017 01:26:51 -0800 Subject: [PATCH 108/111] Update to syntex 0.54 --- serde_codegen/Cargo.toml | 4 ++-- serde_codegen/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 4217841d..ca8b7581 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -25,5 +25,5 @@ clippy = { version = "^0.*", optional = true } quote = "0.3.8" serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" } syn = { version = "0.10", features = ["aster", "visit"] } -syntex = { version = "^0.52.0", optional = true } -syntex_syntax = { version = "^0.52.0", optional = true } +syntex = { version = "^0.54.0", optional = true } +syntex_syntax = { version = "^0.54.0", optional = true } diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 797082b7..f920dda5 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -116,7 +116,7 @@ macro_rules! shim { use syntax::{attr, ast, visit}; struct MarkSerdeAttributesUsed; - impl visit::Visitor for MarkSerdeAttributesUsed { + impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed { fn visit_attribute(&mut self, attr: &ast::Attribute) { if attr.value.name == "serde" { if let ast::MetaItemKind::List(..) = attr.value.node { From 894a21bc1f3040fe4feaed38ecedcdb120ebc8c6 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 8 Jan 2017 00:11:11 -0800 Subject: [PATCH 109/111] Remove the proc_macro feature gate --- README.md | 2 -- serde_derive/src/lib.rs | 2 -- .../tests/compile-fail/duplicate-attribute/rename-and-ser.rs | 2 -- .../tests/compile-fail/duplicate-attribute/rename-rename-de.rs | 2 -- .../compile-fail/duplicate-attribute/rename-ser-rename-ser.rs | 2 -- .../tests/compile-fail/duplicate-attribute/rename-ser-rename.rs | 2 -- .../tests/compile-fail/duplicate-attribute/rename-ser-ser.rs | 2 -- .../tests/compile-fail/duplicate-attribute/two-rename-ser.rs | 2 -- serde_derive/tests/compile-fail/str_ref_deser.rs | 2 -- serde_derive/tests/compile-fail/unknown-attribute/container.rs | 2 -- serde_derive/tests/compile-fail/unknown-attribute/field.rs | 2 -- serde_derive/tests/compile-fail/unknown-attribute/variant.rs | 2 -- serde_derive/tests/run-pass/identity-op.rs | 1 - serde_derive/tests/test.rs | 2 +- 14 files changed, 1 insertion(+), 26 deletions(-) diff --git a/README.md b/README.md index 9f480b18..b46ceef3 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,6 @@ You may be looking for: ## Serde in action ```rust -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs index c625404e..38953f5b 100644 --- a/serde_derive/src/lib.rs +++ b/serde_derive/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro, proc_macro_lib)] - extern crate proc_macro; extern crate serde_codegen; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs index 2f3950f8..2f904a1f 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-and-ser.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs index 04718a0e..bd7be3ad 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-rename-de.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs index 420182c4..6ca7c8f8 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename-ser.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs index 52715b9d..afe343b1 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-rename.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs index 31264c6b..8d50c256 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/rename-ser-ser.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs index d6054529..94b67cff 100644 --- a/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs +++ b/serde_derive/tests/compile-fail/duplicate-attribute/two-rename-ser.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/str_ref_deser.rs b/serde_derive/tests/compile-fail/str_ref_deser.rs index 58ae577c..08c9b1f9 100644 --- a/serde_derive/tests/compile-fail/str_ref_deser.rs +++ b/serde_derive/tests/compile-fail/str_ref_deser.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/unknown-attribute/container.rs b/serde_derive/tests/compile-fail/unknown-attribute/container.rs index 575cc10c..59abfe1d 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/container.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/container.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/unknown-attribute/field.rs b/serde_derive/tests/compile-fail/unknown-attribute/field.rs index 457ce520..66142ce3 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/field.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/field.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs index af5c323a..9b95ec0a 100644 --- a/serde_derive/tests/compile-fail/unknown-attribute/variant.rs +++ b/serde_derive/tests/compile-fail/unknown-attribute/variant.rs @@ -1,5 +1,3 @@ -#![feature(proc_macro)] - #[macro_use] extern crate serde_derive; diff --git a/serde_derive/tests/run-pass/identity-op.rs b/serde_derive/tests/run-pass/identity-op.rs index 0def143e..e1638025 100644 --- a/serde_derive/tests/run-pass/identity-op.rs +++ b/serde_derive/tests/run-pass/identity-op.rs @@ -1,4 +1,3 @@ -#![feature(proc_macro)] #![deny(identity_op)] #[macro_use] diff --git a/serde_derive/tests/test.rs b/serde_derive/tests/test.rs index fde3cfa2..b1969a8f 100644 --- a/serde_derive/tests/test.rs +++ b/serde_derive/tests/test.rs @@ -1,4 +1,4 @@ -#![feature(test, proc_macro)] +#![feature(test)] #[macro_use] extern crate serde_derive; From e461a2379840fc1cac1986ac3530497bdba57851 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 8 Jan 2017 00:18:37 -0800 Subject: [PATCH 110/111] Not intended to be published --- examples/serde-syntex-example/Cargo.toml | 1 + testing/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/serde-syntex-example/Cargo.toml b/examples/serde-syntex-example/Cargo.toml index 9a150821..3c4527da 100644 --- a/examples/serde-syntex-example/Cargo.toml +++ b/examples/serde-syntex-example/Cargo.toml @@ -3,6 +3,7 @@ name = "serde-syntex-example" version = "0.1.0" authors = ["Erick Tryzelaar "] build = "build.rs" +publish = false [features] default = ["serde_codegen"] diff --git a/testing/Cargo.toml b/testing/Cargo.toml index 6c19d8d1..debc8aa8 100644 --- a/testing/Cargo.toml +++ b/testing/Cargo.toml @@ -10,6 +10,7 @@ documentation = "https://docs.serde.rs/serde/" readme = "README.md" keywords = ["serialization"] build = "build.rs" +publish = false [features] unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"] From ad34c14c8c62e0a0c1aa7ed94751934adeed229a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 8 Jan 2017 00:18:53 -0800 Subject: [PATCH 111/111] Prepare for 0.9 breaking changes --- serde/Cargo.toml | 2 ++ serde_codegen/Cargo.toml | 2 ++ serde_codegen_internals/Cargo.toml | 2 ++ serde_derive/Cargo.toml | 2 ++ serde_test/Cargo.toml | 2 ++ 5 files changed, 10 insertions(+) diff --git a/serde/Cargo.toml b/serde/Cargo.toml index c33ff331..4225585e 100644 --- a/serde/Cargo.toml +++ b/serde/Cargo.toml @@ -11,6 +11,8 @@ readme = "../README.md" keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] +publish = false # this branch contains breaking changes for 0.9 + [features] default = ["std"] diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index ca8b7581..39261519 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -10,6 +10,8 @@ documentation = "https://serde.rs/codegen.html" keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] +publish = false # this branch contains breaking changes for 0.9 + [features] default = ["with-syntex"] unstable = [] diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index f03cacd8..f98310f2 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -10,6 +10,8 @@ documentation = "https://docs.serde.rs/serde_codegen_internals/" keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] +publish = false # this branch contains breaking changes for 0.9 + [features] unstable-testing = ["clippy"] diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml index 053732e0..2765340b 100644 --- a/serde_derive/Cargo.toml +++ b/serde_derive/Cargo.toml @@ -10,6 +10,8 @@ documentation = "https://serde.rs/codegen.html" keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] +publish = false # this branch contains breaking changes for 0.9 + [lib] name = "serde_derive" proc-macro = true diff --git a/serde_test/Cargo.toml b/serde_test/Cargo.toml index 5e39bbce..a17bf62d 100644 --- a/serde_test/Cargo.toml +++ b/serde_test/Cargo.toml @@ -11,5 +11,7 @@ readme = "../README.md" keywords = ["serde", "serialization"] include = ["Cargo.toml", "src/**/*.rs"] +publish = false # this branch contains breaking changes for 0.9 + [dependencies] serde = { version = "0.8.21", path = "../serde" }