Merge branch 'origin/1.0' into 'origin/fwd'

Conflicts:
    serde/src/macros.rs
This commit is contained in:
David Tolnay
2017-04-10 15:17:46 -07:00
28 changed files with 871 additions and 319 deletions
+2 -2
View File
@@ -1232,7 +1232,7 @@ impl<'de> Deserialize<'de> for Duration {
} }
} }
deserializer.deserialize_struct_field(FieldVisitor) deserializer.deserialize_identifier(FieldVisitor)
} }
} }
@@ -1358,7 +1358,7 @@ impl<'de, Idx: Deserialize<'de>> Deserialize<'de> for std::ops::Range<Idx> {
} }
} }
deserializer.deserialize_struct_field(FieldVisitor) deserializer.deserialize_identifier(FieldVisitor)
} }
} }
+2 -2
View File
@@ -911,8 +911,8 @@ pub trait Deserializer<'de>: Sized {
where V: Visitor<'de>; where V: Visitor<'de>;
/// Hint that the `Deserialize` type is expecting the name of a struct /// Hint that the `Deserialize` type is expecting the name of a struct
/// field. /// field or the discriminant of an enum variant.
fn deserialize_struct_field<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor<'de>; where V: Visitor<'de>;
/// Hint that the `Deserialize` type is expecting an enum value with a /// Hint that the `Deserialize` type is expecting an enum value with a
+11 -11
View File
@@ -108,7 +108,7 @@ impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes map unit_struct newtype_struct tuple_struct struct seq_fixed_size bytes map unit_struct newtype_struct tuple_struct struct
struct_field tuple enum ignored_any byte_buf identifier tuple enum ignored_any byte_buf
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -155,7 +155,7 @@ macro_rules! primitive_deserializer {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
option seq seq_fixed_size bytes map unit_struct newtype_struct option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf tuple_struct struct identifier tuple enum ignored_any byte_buf
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -208,7 +208,7 @@ impl<'de, E> de::Deserializer<'de> for U32Deserializer<E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple ignored_any byte_buf struct identifier tuple ignored_any byte_buf
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -286,7 +286,7 @@ impl<'de, 'a, E> de::Deserializer<'de> for StrDeserializer<'a, E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple ignored_any byte_buf struct identifier tuple ignored_any byte_buf
} }
} }
@@ -351,7 +351,7 @@ impl<'de, E> de::Deserializer<'de> for StringDeserializer<E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple ignored_any byte_buf struct identifier tuple ignored_any byte_buf
} }
} }
@@ -420,7 +420,7 @@ impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple ignored_any byte_buf struct identifier tuple ignored_any byte_buf
} }
} }
@@ -495,7 +495,7 @@ impl<'de, I, T, E> de::Deserializer<'de> for SeqDeserializer<I, E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple enum ignored_any byte_buf struct identifier tuple enum ignored_any byte_buf
} }
} }
@@ -603,7 +603,7 @@ impl<'de, V_> de::Deserializer<'de> for SeqVisitorDeserializer<V_>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple enum ignored_any byte_buf struct identifier tuple enum ignored_any byte_buf
} }
} }
@@ -707,7 +707,7 @@ impl<'de, I, E> de::Deserializer<'de> for MapDeserializer<'de, I, E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
bytes map unit_struct newtype_struct tuple_struct struct struct_field bytes map unit_struct newtype_struct tuple_struct struct identifier
tuple enum ignored_any byte_buf tuple enum ignored_any byte_buf
} }
} }
@@ -804,7 +804,7 @@ impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer<A, B, E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
bytes map unit_struct newtype_struct tuple_struct struct struct_field bytes map unit_struct newtype_struct tuple_struct struct identifier
tuple enum ignored_any byte_buf tuple enum ignored_any byte_buf
} }
@@ -945,7 +945,7 @@ impl<'de, V_> de::Deserializer<'de> for MapVisitorDeserializer<V_>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple enum ignored_any byte_buf struct identifier tuple enum ignored_any byte_buf
} }
} }
+5 -5
View File
@@ -92,8 +92,8 @@ macro_rules! forward_to_deserialize_helper {
(struct<$l:tt, $v:ident>) => { (struct<$l:tt, $v:ident>) => {
forward_to_deserialize_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])} forward_to_deserialize_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
}; };
(struct_field<$l:tt, $v:ident>) => { (identifier<$l:tt, $v:ident>) => {
forward_to_deserialize_method!{deserialize_struct_field<$l, $v>()} forward_to_deserialize_method!{deserialize_identifier<$l, $v>()}
}; };
(tuple<$l:tt, $v:ident>) => { (tuple<$l:tt, $v:ident>) => {
forward_to_deserialize_method!{deserialize_tuple<$l, $v>(len: usize)} forward_to_deserialize_method!{deserialize_tuple<$l, $v>(len: usize)}
@@ -146,7 +146,7 @@ macro_rules! forward_to_deserialize_helper {
/// # forward_to_deserialize! { /// # forward_to_deserialize! {
/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option /// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct /// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// # tuple_struct struct struct_field tuple enum ignored_any /// # tuple_struct struct identifier tuple enum ignored_any
/// # } /// # }
/// # } /// # }
/// # /// #
@@ -179,7 +179,7 @@ macro_rules! forward_to_deserialize_helper {
/// forward_to_deserialize! { /// forward_to_deserialize! {
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option /// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct /// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any /// tuple_struct struct identifier tuple enum ignored_any
/// } /// }
/// } /// }
/// # /// #
@@ -214,7 +214,7 @@ macro_rules! forward_to_deserialize_helper {
/// <W: Visitor<'q>> /// <W: Visitor<'q>>
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option /// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct /// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any /// tuple_struct struct identifier tuple enum ignored_any
/// } /// }
/// # } /// # }
/// # /// #
+7 -7
View File
@@ -52,7 +52,7 @@ pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct newtype_struct seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any tuple_struct struct identifier tuple enum ignored_any
} }
} }
@@ -855,7 +855,7 @@ mod content {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
struct_field tuple ignored_any identifier tuple ignored_any
} }
} }
@@ -996,7 +996,7 @@ mod content {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any tuple_struct struct identifier tuple enum ignored_any
} }
} }
@@ -1085,7 +1085,7 @@ mod content {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any tuple_struct struct identifier tuple enum ignored_any
} }
} }
@@ -1202,7 +1202,7 @@ mod content {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
struct_field tuple ignored_any identifier tuple ignored_any
} }
} }
@@ -1341,7 +1341,7 @@ mod content {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any tuple_struct struct identifier tuple enum ignored_any
} }
} }
@@ -1430,7 +1430,7 @@ mod content {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any tuple_struct struct identifier tuple enum ignored_any
} }
} }
+4 -4
View File
@@ -66,13 +66,13 @@ macro_rules! __serialize_unimplemented_helper {
__serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok); __serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok);
}; };
(unit_variant) => { (unit_variant) => {
__serialize_unimplemented_method!(serialize_unit_variant(&str, usize, &str) -> Ok); __serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok);
}; };
(newtype_struct) => { (newtype_struct) => {
__serialize_unimplemented_method!(serialize_newtype_struct<T>(&str, &T) -> Ok); __serialize_unimplemented_method!(serialize_newtype_struct<T>(&str, &T) -> Ok);
}; };
(newtype_variant) => { (newtype_variant) => {
__serialize_unimplemented_method!(serialize_newtype_variant<T>(&str, usize, &str, &T) -> Ok); __serialize_unimplemented_method!(serialize_newtype_variant<T>(&str, u32, &str, &T) -> Ok);
}; };
(seq) => { (seq) => {
type SerializeSeq = $crate::ser::Impossible<Self::Ok, Self::Error>; type SerializeSeq = $crate::ser::Impossible<Self::Ok, Self::Error>;
@@ -91,7 +91,7 @@ macro_rules! __serialize_unimplemented_helper {
}; };
(tuple_variant) => { (tuple_variant) => {
type SerializeTupleVariant = $crate::ser::Impossible<Self::Ok, Self::Error>; type SerializeTupleVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_variant(&str, usize, &str, usize) -> SerializeTupleVariant); __serialize_unimplemented_method!(serialize_tuple_variant(&str, u32, &str, usize) -> SerializeTupleVariant);
}; };
(map) => { (map) => {
type SerializeMap = $crate::ser::Impossible<Self::Ok, Self::Error>; type SerializeMap = $crate::ser::Impossible<Self::Ok, Self::Error>;
@@ -103,7 +103,7 @@ macro_rules! __serialize_unimplemented_helper {
}; };
(struct_variant) => { (struct_variant) => {
type SerializeStructVariant = $crate::ser::Impossible<Self::Ok, Self::Error>; type SerializeStructVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct_variant(&str, usize, &str, usize) -> SerializeStructVariant); __serialize_unimplemented_method!(serialize_struct_variant(&str, u32, &str, usize) -> SerializeStructVariant);
}; };
} }
+22 -16
View File
@@ -8,6 +8,12 @@ use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMap
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::error; use std::error;
/// Used to check that serde(getter) attributes return the expected type.
/// Not public API.
pub fn constrain<T: ?Sized>(t: &T) -> &T {
t
}
/// Not public API. /// Not public API.
pub fn serialize_tagged_newtype<S, T>(serializer: S, pub fn serialize_tagged_newtype<S, T>(serializer: S,
type_ident: &'static str, type_ident: &'static str,
@@ -184,7 +190,7 @@ impl<S> Serializer for TaggedSerializer<S>
fn serialize_unit_variant(self, fn serialize_unit_variant(self,
_: &'static str, _: &'static str,
_: usize, _: u32,
inner_variant: &'static str) inner_variant: &'static str)
-> Result<Self::Ok, Self::Error> { -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2))); let mut map = try!(self.delegate.serialize_map(Some(2)));
@@ -204,7 +210,7 @@ impl<S> Serializer for TaggedSerializer<S>
fn serialize_newtype_variant<T: ?Sized>(self, fn serialize_newtype_variant<T: ?Sized>(self,
_: &'static str, _: &'static str,
_: usize, _: u32,
inner_variant: &'static str, inner_variant: &'static str,
inner_value: &T) inner_value: &T)
-> Result<Self::Ok, Self::Error> -> Result<Self::Ok, Self::Error>
@@ -238,7 +244,7 @@ impl<S> Serializer for TaggedSerializer<S>
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_tuple_variant(self, fn serialize_tuple_variant(self,
_: &'static str, _: &'static str,
_: usize, _: u32,
_: &'static str, _: &'static str,
_: usize) _: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> { -> Result<Self::SerializeTupleVariant, Self::Error> {
@@ -250,7 +256,7 @@ impl<S> Serializer for TaggedSerializer<S>
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
fn serialize_tuple_variant(self, fn serialize_tuple_variant(self,
_: &'static str, _: &'static str,
_: usize, _: u32,
inner_variant: &'static str, inner_variant: &'static str,
len: usize) len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> { -> Result<Self::SerializeTupleVariant, Self::Error> {
@@ -278,7 +284,7 @@ impl<S> Serializer for TaggedSerializer<S>
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_struct_variant(self, fn serialize_struct_variant(self,
_: &'static str, _: &'static str,
_: usize, _: u32,
_: &'static str, _: &'static str,
_: usize) _: usize)
-> Result<Self::SerializeStructVariant, Self::Error> { -> Result<Self::SerializeStructVariant, Self::Error> {
@@ -290,7 +296,7 @@ impl<S> Serializer for TaggedSerializer<S>
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
fn serialize_struct_variant(self, fn serialize_struct_variant(self,
_: &'static str, _: &'static str,
_: usize, _: u32,
inner_variant: &'static str, inner_variant: &'static str,
len: usize) len: usize)
-> Result<Self::SerializeStructVariant, Self::Error> { -> Result<Self::SerializeStructVariant, Self::Error> {
@@ -444,18 +450,18 @@ mod content {
Unit, Unit,
UnitStruct(&'static str), UnitStruct(&'static str),
UnitVariant(&'static str, usize, &'static str), UnitVariant(&'static str, u32, &'static str),
NewtypeStruct(&'static str, Box<Content>), NewtypeStruct(&'static str, Box<Content>),
NewtypeVariant(&'static str, usize, &'static str, Box<Content>), NewtypeVariant(&'static str, u32, &'static str, Box<Content>),
Seq(Vec<Content>), Seq(Vec<Content>),
SeqFixedSize(Vec<Content>), SeqFixedSize(Vec<Content>),
Tuple(Vec<Content>), Tuple(Vec<Content>),
TupleStruct(&'static str, Vec<Content>), TupleStruct(&'static str, Vec<Content>),
TupleVariant(&'static str, usize, &'static str, Vec<Content>), TupleVariant(&'static str, u32, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>), Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>), Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>), StructVariant(&'static str, u32, &'static str, Vec<(&'static str, Content)>),
} }
impl Serialize for Content { impl Serialize for Content {
@@ -645,7 +651,7 @@ mod content {
fn serialize_unit_variant(self, fn serialize_unit_variant(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str) variant: &'static str)
-> Result<Content, E> { -> Result<Content, E> {
Ok(Content::UnitVariant(name, variant_index, variant)) Ok(Content::UnitVariant(name, variant_index, variant))
@@ -660,7 +666,7 @@ mod content {
fn serialize_newtype_variant<T: ?Sized + Serialize>(self, fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
value: &T) value: &T)
-> Result<Content, E> { -> Result<Content, E> {
@@ -706,7 +712,7 @@ mod content {
fn serialize_tuple_variant(self, fn serialize_tuple_variant(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
len: usize) len: usize)
-> Result<Self::SerializeTupleVariant, E> { -> Result<Self::SerializeTupleVariant, E> {
@@ -737,7 +743,7 @@ mod content {
fn serialize_struct_variant(self, fn serialize_struct_variant(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
len: usize) len: usize)
-> Result<Self::SerializeStructVariant, E> { -> Result<Self::SerializeStructVariant, E> {
@@ -825,7 +831,7 @@ mod content {
struct SerializeTupleVariant<E> { struct SerializeTupleVariant<E> {
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
fields: Vec<Content>, fields: Vec<Content>,
error: PhantomData<E>, error: PhantomData<E>,
@@ -916,7 +922,7 @@ mod content {
struct SerializeStructVariant<E> { struct SerializeStructVariant<E> {
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
fields: Vec<(&'static str, Content)>, fields: Vec<(&'static str, Content)>,
error: PhantomData<E>, error: PhantomData<E>,
+4 -4
View File
@@ -449,7 +449,7 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_unit_variant(self, fn serialize_unit_variant(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str) variant: &'static str)
-> Result<Self::Ok, Self::Error>; -> Result<Self::Ok, Self::Error>;
@@ -504,7 +504,7 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_newtype_variant<T: ?Sized + Serialize>(self, fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
value: &T) value: &T)
-> Result<Self::Ok, Self::Error>; -> Result<Self::Ok, Self::Error>;
@@ -686,7 +686,7 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_tuple_variant(self, fn serialize_tuple_variant(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
len: usize) len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error>; -> Result<Self::SerializeTupleVariant, Self::Error>;
@@ -806,7 +806,7 @@ pub trait Serializer: Sized {
/// ``` /// ```
fn serialize_struct_variant(self, fn serialize_struct_variant(self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: u32,
variant: &'static str, variant: &'static str,
len: usize) len: usize)
-> Result<Self::SerializeStructVariant, Self::Error>; -> Result<Self::SerializeStructVariant, Self::Error>;
+9 -2
View File
@@ -1,5 +1,6 @@
use syn; use syn;
use attr; use attr;
use check;
use Ctxt; use Ctxt;
pub struct Item<'a> { pub struct Item<'a> {
@@ -62,12 +63,14 @@ impl<'a> Item<'a> {
} }
} }
Item { let item = Item {
ident: item.ident.clone(), ident: item.ident.clone(),
attrs: attrs, attrs: attrs,
body: body, body: body,
generics: &item.generics, generics: &item.generics,
} };
check::check(cx, &item);
item
} }
} }
@@ -81,6 +84,10 @@ impl<'a> Body<'a> {
Body::Struct(_, ref fields) => Box::new(fields.iter()), Body::Struct(_, ref fields) => Box::new(fields.iter()),
} }
} }
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
} }
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> { fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
+28
View File
@@ -102,6 +102,7 @@ pub struct Item {
tag: EnumTag, tag: EnumTag,
from_type: Option<syn::Ty>, from_type: Option<syn::Ty>,
into_type: Option<syn::Ty>, into_type: Option<syn::Ty>,
remote: Option<syn::Path>,
} }
/// Styles of representing an enum. /// Styles of representing an enum.
@@ -151,6 +152,7 @@ impl Item {
let mut content = Attr::none(cx, "content"); let mut content = Attr::none(cx, "content");
let mut from_type = Attr::none(cx, "from"); let mut from_type = Attr::none(cx, "from");
let mut into_type = Attr::none(cx, "into"); let mut into_type = Attr::none(cx, "into");
let mut remote = Attr::none(cx, "remote");
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 { for meta_item in meta_items {
@@ -290,6 +292,13 @@ impl Item {
} }
} }
// Parse `#[serde(remote = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "remote" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
remote.set(path);
}
}
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`", cx.error(format!("unknown serde container attribute `{}`",
meta_item.name())); meta_item.name()));
@@ -361,6 +370,7 @@ impl Item {
tag: tag, tag: tag,
from_type: from_type.get(), from_type: from_type.get(),
into_type: into_type.get(), into_type: into_type.get(),
remote: remote.get(),
} }
} }
@@ -399,6 +409,10 @@ impl Item {
pub fn into_type(&self) -> Option<&syn::Ty> { pub fn into_type(&self) -> Option<&syn::Ty> {
self.into_type.as_ref() self.into_type.as_ref()
} }
pub fn remote(&self) -> Option<&syn::Path> {
self.remote.as_ref()
}
} }
/// Represents variant attribute information /// Represents variant attribute information
@@ -531,6 +545,7 @@ pub struct Field {
ser_bound: Option<Vec<syn::WherePredicate>>, ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>, de_bound: Option<Vec<syn::WherePredicate>>,
borrowed_lifetimes: BTreeSet<syn::Lifetime>, borrowed_lifetimes: BTreeSet<syn::Lifetime>,
getter: Option<syn::Path>,
} }
/// Represents the default to use for a field when deserializing. /// Represents the default to use for a field when deserializing.
@@ -558,6 +573,7 @@ impl Field {
let mut ser_bound = Attr::none(cx, "bound"); let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound"); let mut de_bound = Attr::none(cx, "bound");
let mut borrowed_lifetimes = Attr::none(cx, "borrow"); let mut borrowed_lifetimes = Attr::none(cx, "borrow");
let mut getter = Attr::none(cx, "getter");
let ident = match field.ident { let ident = match field.ident {
Some(ref ident) => ident.to_string(), Some(ref ident) => ident.to_string(),
@@ -676,6 +692,13 @@ impl Field {
} }
} }
// Parse `#[serde(getter = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "getter" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
getter.set(path);
}
}
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`", meta_item.name())); cx.error(format!("unknown serde field attribute `{}`", meta_item.name()));
} }
@@ -737,6 +760,7 @@ impl Field {
ser_bound: ser_bound.get(), ser_bound: ser_bound.get(),
de_bound: de_bound.get(), de_bound: de_bound.get(),
borrowed_lifetimes: borrowed_lifetimes, borrowed_lifetimes: borrowed_lifetimes,
getter: getter.get(),
} }
} }
@@ -788,6 +812,10 @@ impl Field {
pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> { pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> {
&self.borrowed_lifetimes &self.borrowed_lifetimes
} }
pub fn getter(&self) -> Option<&syn::Path> {
self.getter.as_ref()
}
} }
type SerAndDe<T> = (Option<T>, Option<T>); type SerAndDe<T> = (Option<T>, Option<T>);
+20
View File
@@ -0,0 +1,20 @@
use ast::{Body, Item};
use Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, item: &Item) {
match item.body {
Body::Enum(_) => {
if item.body.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Body::Struct(_, _) => {
if item.body.has_getter() && item.attrs.remote().is_none() {
cx.error("#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]");
}
}
}
}
+1
View File
@@ -9,3 +9,4 @@ mod ctxt;
pub use ctxt::Ctxt; pub use ctxt::Ctxt;
mod case; mod case;
mod check;
+219 -140
View File
@@ -14,17 +14,25 @@ pub fn expand_derive_deserialize(item: &syn::DeriveInput) -> Result<Tokens, Stri
try!(ctxt.check()); try!(ctxt.check());
let ident = &item.ident; let ident = &item.ident;
let generics = build_generics(&item); let params = Parameters::new(&item);
let borrowed = borrowed_lifetimes(&item);
let params = Parameters { generics: generics, borrowed: borrowed };
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident)); let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident));
let body = Stmts(deserialize_body(&item, &params)); let body = Stmts(deserialize_body(&item, &params));
Ok(quote! { let impl_item = if let Some(remote) = item.attrs.remote() {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
const #dummy_const: () = { let de_lifetime = params.de_lifetime_def();
extern crate serde as _serde; quote! {
impl #impl_generics #ident #ty_generics #where_clause {
fn deserialize<#de_lifetime, __D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<'de>
{
#body
}
}
}
} else {
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
quote! {
#[automatically_derived] #[automatically_derived]
impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause { impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error> fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
@@ -33,13 +41,72 @@ pub fn expand_derive_deserialize(item: &syn::DeriveInput) -> Result<Tokens, Stri
#body #body
} }
} }
}
};
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#impl_item
}; };
}) })
} }
struct Parameters { struct Parameters {
/// Name of the type the `derive` is on.
local: syn::Ident,
/// Path to the type the impl is for. Either a single `Ident` for local
/// types or `some::remote::Ident` for remote types. Does not include
/// generic parameters.
this: syn::Path,
/// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics, generics: syn::Generics,
/// Lifetimes borrowed from the deserializer. These will become bounds on
/// the `'de` lifetime of the deserializer.
borrowed: BTreeSet<syn::Lifetime>, borrowed: BTreeSet<syn::Lifetime>,
/// At least one field has a serde(getter) attribute, implying that the
/// remote type has a private field.
has_getter: bool,
}
impl Parameters {
fn new(item: &Item) -> Self {
let local = item.ident.clone();
let this = match item.attrs.remote() {
Some(remote) => remote.clone(),
None => item.ident.clone().into(),
};
let generics = build_generics(item);
let borrowed = borrowed_lifetimes(item);
let has_getter = item.body.has_getter();
Parameters {
local: local,
this: this,
generics: generics,
borrowed: borrowed,
has_getter: has_getter,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Deserializer methods.
fn type_name(&self) -> &str {
self.this.segments.last().unwrap().ident.as_ref()
}
fn de_lifetime_def(&self) -> syn::LifetimeDef {
syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de"),
bounds: self.borrowed.iter().cloned().collect(),
}
}
} }
// All the generics in the input, plus a bound `T: Deserialize` for each generic // All the generics in the input, plus a bound `T: Deserialize` for each generic
@@ -109,14 +176,13 @@ fn deserialize_body(item: &Item, params: &Parameters) -> Fragment {
} else { } else {
match item.body { match item.body {
Body::Enum(ref variants) => { Body::Enum(ref variants) => {
deserialize_item_enum(&item.ident, params, variants, &item.attrs) deserialize_item_enum(params, variants, &item.attrs)
} }
Body::Struct(Style::Struct, ref fields) => { Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) { if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields"); panic!("struct has unnamed fields");
} }
deserialize_struct(&item.ident, deserialize_struct(None,
None,
params, params,
fields, fields,
&item.attrs, &item.attrs,
@@ -127,14 +193,13 @@ fn deserialize_body(item: &Item, params: &Parameters) -> Fragment {
if fields.iter().any(|field| field.ident.is_some()) { if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields"); panic!("tuple struct has named fields");
} }
deserialize_tuple(&item.ident, deserialize_tuple(None,
None,
params, params,
fields, fields,
&item.attrs, &item.attrs,
None) None)
} }
Body::Struct(Style::Unit, _) => deserialize_unit_struct(&item.ident, &item.attrs), Body::Struct(Style::Unit, _) => deserialize_unit_struct(params, &item.attrs),
} }
} }
} }
@@ -147,33 +212,27 @@ fn deserialize_from(from_type: &syn::Ty) -> Fragment {
} }
} }
fn deserialize_unit_struct(ident: &syn::Ident, item_attrs: &attr::Item) -> Fragment { fn deserialize_unit_struct(params: &Parameters, item_attrs: &attr::Item) -> Fragment {
let this = &params.this;
let type_name = item_attrs.name().deserialize_name(); let type_name = item_attrs.name().deserialize_name();
let expecting = format!("unit struct {}", ident); let expecting = format!("unit struct {}", params.type_name());
quote_block! { quote_block! {
struct __Visitor; struct __Visitor;
impl<'de> _serde::de::Visitor<'de> for __Visitor { impl<'de> _serde::de::Visitor<'de> for __Visitor {
type Value = #ident; type Value = #this;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
_serde::export::fmt::Formatter::write_str(formatter, #expecting) _serde::export::fmt::Formatter::write_str(formatter, #expecting)
} }
#[inline] #[inline]
fn visit_unit<__E>(self) -> _serde::export::Result<#ident, __E> fn visit_unit<__E>(self) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error where __E: _serde::de::Error
{ {
_serde::export::Ok(#ident) _serde::export::Ok(#this)
}
#[inline]
fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#ident, __V::Error>
where __V: _serde::de::SeqVisitor<'de>
{
_serde::export::Ok(#ident)
} }
} }
@@ -181,38 +240,48 @@ fn deserialize_unit_struct(ident: &syn::Ident, item_attrs: &attr::Item) -> Fragm
} }
} }
fn deserialize_tuple(ident: &syn::Ident, fn deserialize_tuple(variant_ident: Option<&syn::Ident>,
variant_ident: Option<&syn::Ident>,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item, item_attrs: &attr::Item,
deserializer: Option<Tokens>) deserializer: Option<Tokens>)
-> Fragment { -> Fragment {
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
// If there are getters (implying private fields), construct the local type
// and use an `Into` conversion to get the remote type. If there are no
// getters then construct the target type directly.
let construct = if params.has_getter {
let local = &params.local;
quote!(#local)
} else {
quote!(#this)
};
let is_enum = variant_ident.is_some(); let is_enum = variant_ident.is_some();
let type_path = match variant_ident { let type_path = match variant_ident {
Some(variant_ident) => quote!(#ident::#variant_ident), Some(variant_ident) => quote!(#construct::#variant_ident),
None => quote!(#ident), None => construct,
}; };
let expecting = match variant_ident { let expecting = match variant_ident {
Some(variant_ident) => format!("tuple variant {}::{}", ident, variant_ident), Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
None => format!("tuple struct {}", ident), None => format!("tuple struct {}", params.type_name()),
}; };
let nfields = fields.len(); let nfields = fields.len();
let visit_newtype_struct = if !is_enum && nfields == 1 { let visit_newtype_struct = if !is_enum && nfields == 1 {
Some(deserialize_newtype_struct(ident, &type_path, params, &fields[0])) Some(deserialize_newtype_struct(&type_path, params, &fields[0]))
} else { } else {
None None
}; };
let visit_seq = Stmts(deserialize_seq(ident, &type_path, params, fields, false, item_attrs)); let visit_seq = Stmts(deserialize_seq(&type_path, params, fields, false, item_attrs));
let visitor_expr = quote! { let visitor_expr = quote! {
__Visitor { __Visitor {
marker: _serde::export::PhantomData::<#ident #ty_generics>, marker: _serde::export::PhantomData::<#this #ty_generics>,
lifetime: _serde::export::PhantomData, lifetime: _serde::export::PhantomData,
} }
}; };
@@ -237,12 +306,12 @@ fn deserialize_tuple(ident: &syn::Ident,
quote_block! { quote_block! {
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::export::PhantomData<#ident #ty_generics>, marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&'de ()>, lifetime: _serde::export::PhantomData<&'de ()>,
} }
impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause {
type Value = #ident #ty_generics; type Value = #this #ty_generics;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
_serde::export::fmt::Formatter::write_str(formatter, #expecting) _serde::export::fmt::Formatter::write_str(formatter, #expecting)
@@ -262,8 +331,7 @@ fn deserialize_tuple(ident: &syn::Ident,
} }
} }
fn deserialize_seq(ident: &syn::Ident, fn deserialize_seq(type_path: &Tokens,
type_path: &Tokens,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
is_struct: bool, is_struct: bool,
@@ -292,7 +360,7 @@ fn deserialize_seq(ident: &syn::Ident,
} }
Some(path) => { Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_with( let (wrapper, wrapper_ty) = wrap_deserialize_with(
ident, params, field.ty, path); params, field.ty, path);
quote!({ quote!({
#wrapper #wrapper
_serde::export::Option::map( _serde::export::Option::map(
@@ -314,7 +382,7 @@ fn deserialize_seq(ident: &syn::Ident,
} }
}); });
let result = if is_struct { let mut result = if is_struct {
let names = fields.iter().map(|f| &f.ident); let names = fields.iter().map(|f| &f.ident);
quote! { quote! {
#type_path { #( #names: #vars ),* } #type_path { #( #names: #vars ),* }
@@ -325,14 +393,20 @@ fn deserialize_seq(ident: &syn::Ident,
} }
}; };
if params.has_getter {
let this = &params.this;
result = quote! {
_serde::export::Into::<#this>::into(#result)
};
}
quote_block! { quote_block! {
#(#let_values)* #(#let_values)*
_serde::export::Ok(#result) _serde::export::Ok(#result)
} }
} }
fn deserialize_newtype_struct(ident: &syn::Ident, fn deserialize_newtype_struct(type_path: &Tokens,
type_path: &Tokens,
params: &Parameters, params: &Parameters,
field: &Field) field: &Field)
-> Tokens { -> Tokens {
@@ -345,25 +419,33 @@ fn deserialize_newtype_struct(ident: &syn::Ident,
} }
Some(path) => { Some(path) => {
let (wrapper, wrapper_ty) = let (wrapper, wrapper_ty) =
wrap_deserialize_with(ident, params, field.ty, path); wrap_deserialize_with(params, field.ty, path);
quote!({ quote!({
#wrapper #wrapper
try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value
}) })
} }
}; };
let mut result = quote!(#type_path(#value));
if params.has_getter {
let this = &params.this;
result = quote! {
_serde::export::Into::<#this>::into(#result)
};
}
quote! { quote! {
#[inline] #[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error> fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer<'de> where __E: _serde::Deserializer<'de>
{ {
_serde::export::Ok(#type_path(#value)) _serde::export::Ok(#result)
} }
} }
} }
fn deserialize_struct(ident: &syn::Ident, fn deserialize_struct(variant_ident: Option<&syn::Ident>,
variant_ident: Option<&syn::Ident>,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item, item_attrs: &attr::Item,
@@ -372,28 +454,39 @@ fn deserialize_struct(ident: &syn::Ident,
let is_enum = variant_ident.is_some(); let is_enum = variant_ident.is_some();
let is_untagged = deserializer.is_some(); let is_untagged = deserializer.is_some();
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
// If there are getters (implying private fields), construct the local type
// and use an `Into` conversion to get the remote type. If there are no
// getters then construct the target type directly.
let construct = if params.has_getter {
let local = &params.local;
quote!(#local)
} else {
quote!(#this)
};
let type_path = match variant_ident { let type_path = match variant_ident {
Some(variant_ident) => quote!(#ident::#variant_ident), Some(variant_ident) => quote!(#construct::#variant_ident),
None => quote!(#ident), None => construct,
}; };
let expecting = match variant_ident { let expecting = match variant_ident {
Some(variant_ident) => format!("struct variant {}::{}", ident, variant_ident), Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
None => format!("struct {}", ident), None => format!("struct {}", params.type_name()),
}; };
let visit_seq = Stmts(deserialize_seq(ident, &type_path, params, fields, true, item_attrs)); let visit_seq = Stmts(deserialize_seq(&type_path, params, fields, true, item_attrs));
let (field_visitor, fields_stmt, visit_map) = let (field_visitor, fields_stmt, visit_map) =
deserialize_struct_visitor(ident, type_path, params, fields, item_attrs); deserialize_struct_visitor(type_path, params, fields, item_attrs);
let field_visitor = Stmts(field_visitor); let field_visitor = Stmts(field_visitor);
let fields_stmt = Stmts(fields_stmt); let fields_stmt = Stmts(fields_stmt);
let visit_map = Stmts(visit_map); let visit_map = Stmts(visit_map);
let visitor_expr = quote! { let visitor_expr = quote! {
__Visitor { __Visitor {
marker: _serde::export::PhantomData::<#ident #ty_generics>, marker: _serde::export::PhantomData::<#this #ty_generics>,
lifetime: _serde::export::PhantomData, lifetime: _serde::export::PhantomData,
} }
}; };
@@ -437,12 +530,12 @@ fn deserialize_struct(ident: &syn::Ident,
#field_visitor #field_visitor
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::export::PhantomData<#ident #ty_generics>, marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&'de ()>, lifetime: _serde::export::PhantomData<&'de ()>,
} }
impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause {
type Value = #ident #ty_generics; type Value = #this #ty_generics;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
_serde::export::fmt::Formatter::write_str(formatter, #expecting) _serde::export::fmt::Formatter::write_str(formatter, #expecting)
@@ -464,46 +557,43 @@ fn deserialize_struct(ident: &syn::Ident,
} }
} }
fn deserialize_item_enum(ident: &syn::Ident, fn deserialize_item_enum(params: &Parameters,
params: &Parameters,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
match *item_attrs.tag() { match *item_attrs.tag() {
attr::EnumTag::External => { attr::EnumTag::External => {
deserialize_externally_tagged_enum(ident, params, variants, item_attrs) deserialize_externally_tagged_enum(params, variants, item_attrs)
} }
attr::EnumTag::Internal { ref tag } => { attr::EnumTag::Internal { ref tag } => {
deserialize_internally_tagged_enum(ident, deserialize_internally_tagged_enum(params,
params,
variants, variants,
item_attrs, item_attrs,
tag) tag)
} }
attr::EnumTag::Adjacent { ref tag, ref content } => { attr::EnumTag::Adjacent { ref tag, ref content } => {
deserialize_adjacently_tagged_enum(ident, deserialize_adjacently_tagged_enum(params,
params,
variants, variants,
item_attrs, item_attrs,
tag, tag,
content) content)
} }
attr::EnumTag::None => { attr::EnumTag::None => {
deserialize_untagged_enum(ident, params, variants, item_attrs) deserialize_untagged_enum(params, variants, item_attrs)
} }
} }
} }
fn deserialize_externally_tagged_enum(ident: &syn::Ident, fn deserialize_externally_tagged_enum(params: &Parameters,
params: &Parameters,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
let type_name = item_attrs.name().deserialize_name(); let type_name = item_attrs.name().deserialize_name();
let expecting = format!("enum {}", ident); let expecting = format!("enum {}", params.type_name());
let variant_names_idents: Vec<_> = variants.iter() let variant_names_idents: Vec<_> = variants.iter()
.enumerate() .enumerate()
@@ -527,8 +617,7 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
.map(|(i, variant)| { .map(|(i, variant)| {
let variant_name = field_i(i); let variant_name = field_i(i);
let block = Match(deserialize_externally_tagged_variant(ident, let block = Match(deserialize_externally_tagged_variant(params,
params,
variant, variant,
item_attrs)); item_attrs));
@@ -561,12 +650,12 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
#variant_visitor #variant_visitor
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::export::PhantomData<#ident #ty_generics>, marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&'de ()>, lifetime: _serde::export::PhantomData<&'de ()>,
} }
impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause {
type Value = #ident #ty_generics; type Value = #this #ty_generics;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
_serde::export::fmt::Formatter::write_str(formatter, #expecting) _serde::export::fmt::Formatter::write_str(formatter, #expecting)
@@ -583,14 +672,13 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
_serde::Deserializer::deserialize_enum(__deserializer, #type_name, VARIANTS, _serde::Deserializer::deserialize_enum(__deserializer, #type_name, VARIANTS,
__Visitor { __Visitor {
marker: _serde::export::PhantomData::<#ident #ty_generics>, marker: _serde::export::PhantomData::<#this #ty_generics>,
lifetime: _serde::export::PhantomData, lifetime: _serde::export::PhantomData,
}) })
} }
} }
fn deserialize_internally_tagged_enum(ident: &syn::Ident, fn deserialize_internally_tagged_enum(params: &Parameters,
params: &Parameters,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item, item_attrs: &attr::Item,
tag: &str) tag: &str)
@@ -618,7 +706,6 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident,
let variant_name = field_i(i); let variant_name = field_i(i);
let block = Match(deserialize_internally_tagged_variant( let block = Match(deserialize_internally_tagged_variant(
ident,
params, params,
variant, variant,
item_attrs, item_attrs,
@@ -645,13 +732,13 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident,
} }
} }
fn deserialize_adjacently_tagged_enum(ident: &syn::Ident, fn deserialize_adjacently_tagged_enum(params: &Parameters,
params: &Parameters,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item, item_attrs: &attr::Item,
tag: &str, tag: &str,
content: &str) content: &str)
-> Fragment { -> Fragment {
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
let variant_names_idents: Vec<_> = variants.iter() let variant_names_idents: Vec<_> = variants.iter()
@@ -676,7 +763,6 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
let variant_index = field_i(i); let variant_index = field_i(i);
let block = Match(deserialize_untagged_variant( let block = Match(deserialize_untagged_variant(
ident,
params, params,
variant, variant,
item_attrs, item_attrs,
@@ -689,7 +775,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
}) })
.collect(); .collect();
let expecting = format!("adjacently tagged enum {}", ident); let expecting = format!("adjacently tagged enum {}", params.type_name());
let type_name = item_attrs.name().deserialize_name(); let type_name = item_attrs.name().deserialize_name();
let tag_or_content = quote! { let tag_or_content = quote! {
@@ -724,7 +810,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
let variant_index = field_i(i); let variant_index = field_i(i);
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
quote! { quote! {
__Field::#variant_index => _serde::export::Ok(#ident::#variant_ident), __Field::#variant_index => _serde::export::Ok(#this::#variant_ident),
} }
}); });
missing_content = quote! { missing_content = quote! {
@@ -755,12 +841,12 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
struct __Seed #de_impl_generics #where_clause { struct __Seed #de_impl_generics #where_clause {
field: __Field, field: __Field,
marker: _serde::export::PhantomData<#ident #ty_generics>, marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&'de ()>, lifetime: _serde::export::PhantomData<&'de ()>,
} }
impl #de_impl_generics _serde::de::DeserializeSeed<'de> for __Seed #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::DeserializeSeed<'de> for __Seed #de_ty_generics #where_clause {
type Value = #ident #ty_generics; type Value = #this #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::export::Result<Self::Value, __D::Error> fn deserialize<__D>(self, __deserializer: __D) -> _serde::export::Result<Self::Value, __D::Error>
where __D: _serde::Deserializer<'de> where __D: _serde::Deserializer<'de>
@@ -772,12 +858,12 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
} }
struct __Visitor #de_impl_generics #where_clause { struct __Visitor #de_impl_generics #where_clause {
marker: _serde::export::PhantomData<#ident #ty_generics>, marker: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&'de ()>, lifetime: _serde::export::PhantomData<&'de ()>,
} }
impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause { impl #de_impl_generics _serde::de::Visitor<'de> for __Visitor #de_ty_generics #where_clause {
type Value = #ident #ty_generics; type Value = #this #ty_generics;
fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
_serde::export::fmt::Formatter::write_str(formatter, #expecting) _serde::export::fmt::Formatter::write_str(formatter, #expecting)
@@ -878,14 +964,13 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
const FIELDS: &'static [&'static str] = &[#tag, #content]; const FIELDS: &'static [&'static str] = &[#tag, #content];
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS,
__Visitor { __Visitor {
marker: _serde::export::PhantomData::<#ident #ty_generics>, marker: _serde::export::PhantomData::<#this #ty_generics>,
lifetime: _serde::export::PhantomData, lifetime: _serde::export::PhantomData,
}) })
} }
} }
fn deserialize_untagged_enum(ident: &syn::Ident, fn deserialize_untagged_enum(params: &Parameters,
params: &Parameters,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
@@ -893,7 +978,6 @@ fn deserialize_untagged_enum(ident: &syn::Ident,
.filter(|variant| !variant.attrs.skip_deserializing()) .filter(|variant| !variant.attrs.skip_deserializing())
.map(|variant| { .map(|variant| {
Expr(deserialize_untagged_variant( Expr(deserialize_untagged_variant(
ident,
params, params,
variant, variant,
item_attrs, item_attrs,
@@ -907,7 +991,7 @@ fn deserialize_untagged_enum(ident: &syn::Ident,
// largest number of fields. I'm not sure I like that. Maybe it would be // largest number of fields. I'm not sure I like that. Maybe it would be
// better to save all the errors and combine them into one message that // better to save all the errors and combine them into one message that
// explains why none of the variants matched. // explains why none of the variants matched.
let fallthrough_msg = format!("data did not match any variant of untagged enum {}", ident); let fallthrough_msg = format!("data did not match any variant of untagged enum {}", params.type_name());
quote_block! { quote_block! {
let __content = try!(<_serde::private::de::Content as _serde::Deserialize>::deserialize(__deserializer)); let __content = try!(<_serde::private::de::Content as _serde::Deserialize>::deserialize(__deserializer));
@@ -922,8 +1006,7 @@ fn deserialize_untagged_enum(ident: &syn::Ident,
} }
} }
fn deserialize_externally_tagged_variant(ident: &syn::Ident, fn deserialize_externally_tagged_variant(params: &Parameters,
params: &Parameters,
variant: &Variant, variant: &Variant,
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
@@ -931,28 +1014,26 @@ fn deserialize_externally_tagged_variant(ident: &syn::Ident,
match variant.style { match variant.style {
Style::Unit => { Style::Unit => {
let this = &params.this;
quote_block! { quote_block! {
try!(_serde::de::VariantVisitor::visit_unit(__visitor)); try!(_serde::de::VariantVisitor::visit_unit(__visitor));
_serde::export::Ok(#ident::#variant_ident) _serde::export::Ok(#this::#variant_ident)
} }
} }
Style::Newtype => { Style::Newtype => {
deserialize_externally_tagged_newtype_variant(ident, deserialize_externally_tagged_newtype_variant(variant_ident,
variant_ident,
params, params,
&variant.fields[0]) &variant.fields[0])
} }
Style::Tuple => { Style::Tuple => {
deserialize_tuple(ident, deserialize_tuple(Some(variant_ident),
Some(variant_ident),
params, params,
&variant.fields, &variant.fields,
item_attrs, item_attrs,
None) None)
} }
Style::Struct => { Style::Struct => {
deserialize_struct(ident, deserialize_struct(Some(variant_ident),
Some(variant_ident),
params, params,
&variant.fields, &variant.fields,
item_attrs, item_attrs,
@@ -961,8 +1042,7 @@ fn deserialize_externally_tagged_variant(ident: &syn::Ident,
} }
} }
fn deserialize_internally_tagged_variant(ident: &syn::Ident, fn deserialize_internally_tagged_variant(params: &Parameters,
params: &Parameters,
variant: &Variant, variant: &Variant,
item_attrs: &attr::Item, item_attrs: &attr::Item,
deserializer: Tokens) deserializer: Tokens)
@@ -971,16 +1051,16 @@ fn deserialize_internally_tagged_variant(ident: &syn::Ident,
match variant.style { match variant.style {
Style::Unit => { Style::Unit => {
let type_name = ident.as_ref(); let this = &params.this;
let type_name = params.type_name();
let variant_name = variant.ident.as_ref(); let variant_name = variant.ident.as_ref();
quote_block! { quote_block! {
try!(_serde::Deserializer::deserialize(#deserializer, _serde::private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))); try!(_serde::Deserializer::deserialize(#deserializer, _serde::private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::export::Ok(#ident::#variant_ident) _serde::export::Ok(#this::#variant_ident)
} }
} }
Style::Newtype | Style::Struct => { Style::Newtype | Style::Struct => {
deserialize_untagged_variant(ident, deserialize_untagged_variant(params,
params,
variant, variant,
item_attrs, item_attrs,
deserializer) deserializer)
@@ -989,8 +1069,7 @@ fn deserialize_internally_tagged_variant(ident: &syn::Ident,
} }
} }
fn deserialize_untagged_variant(ident: &syn::Ident, fn deserialize_untagged_variant(params: &Parameters,
params: &Parameters,
variant: &Variant, variant: &Variant,
item_attrs: &attr::Item, item_attrs: &attr::Item,
deserializer: Tokens) deserializer: Tokens)
@@ -999,7 +1078,8 @@ fn deserialize_untagged_variant(ident: &syn::Ident,
match variant.style { match variant.style {
Style::Unit => { Style::Unit => {
let type_name = ident.as_ref(); let this = &params.this;
let type_name = params.type_name();
let variant_name = variant.ident.as_ref(); let variant_name = variant.ident.as_ref();
quote_expr! { quote_expr! {
_serde::export::Result::map( _serde::export::Result::map(
@@ -1007,27 +1087,24 @@ fn deserialize_untagged_variant(ident: &syn::Ident,
#deserializer, #deserializer,
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name) _serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
), ),
|()| #ident::#variant_ident) |()| #this::#variant_ident)
} }
} }
Style::Newtype => { Style::Newtype => {
deserialize_untagged_newtype_variant(ident, deserialize_untagged_newtype_variant(variant_ident,
variant_ident,
params, params,
&variant.fields[0], &variant.fields[0],
deserializer) deserializer)
} }
Style::Tuple => { Style::Tuple => {
deserialize_tuple(ident, deserialize_tuple(Some(variant_ident),
Some(variant_ident),
params, params,
&variant.fields, &variant.fields,
item_attrs, item_attrs,
Some(deserializer)) Some(deserializer))
} }
Style::Struct => { Style::Struct => {
deserialize_struct(ident, deserialize_struct(Some(variant_ident),
Some(variant_ident),
params, params,
&variant.fields, &variant.fields,
item_attrs, item_attrs,
@@ -1036,56 +1113,56 @@ fn deserialize_untagged_variant(ident: &syn::Ident,
} }
} }
fn deserialize_externally_tagged_newtype_variant(ident: &syn::Ident, fn deserialize_externally_tagged_newtype_variant(variant_ident: &syn::Ident,
variant_ident: &syn::Ident,
params: &Parameters, params: &Parameters,
field: &Field) field: &Field)
-> Fragment { -> Fragment {
let this = &params.this;
match field.attrs.deserialize_with() { match field.attrs.deserialize_with() {
None => { None => {
let field_ty = &field.ty; let field_ty = &field.ty;
quote_expr! { quote_expr! {
_serde::export::Result::map( _serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#field_ty>(__visitor), _serde::de::VariantVisitor::visit_newtype::<#field_ty>(__visitor),
#ident::#variant_ident) #this::#variant_ident)
} }
} }
Some(path) => { Some(path) => {
let (wrapper, wrapper_ty) = let (wrapper, wrapper_ty) =
wrap_deserialize_with(ident, params, field.ty, path); wrap_deserialize_with(params, field.ty, path);
quote_block! { quote_block! {
#wrapper #wrapper
_serde::export::Result::map( _serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(__visitor), _serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(__visitor),
|__wrapper| #ident::#variant_ident(__wrapper.value)) |__wrapper| #this::#variant_ident(__wrapper.value))
} }
} }
} }
} }
fn deserialize_untagged_newtype_variant(ident: &syn::Ident, fn deserialize_untagged_newtype_variant(variant_ident: &syn::Ident,
variant_ident: &syn::Ident,
params: &Parameters, params: &Parameters,
field: &Field, field: &Field,
deserializer: Tokens) deserializer: Tokens)
-> Fragment { -> Fragment {
let this = &params.this;
match field.attrs.deserialize_with() { match field.attrs.deserialize_with() {
None => { None => {
let field_ty = &field.ty; let field_ty = &field.ty;
quote_expr! { quote_expr! {
_serde::export::Result::map( _serde::export::Result::map(
<#field_ty as _serde::Deserialize>::deserialize(#deserializer), <#field_ty as _serde::Deserialize>::deserialize(#deserializer),
#ident::#variant_ident) #this::#variant_ident)
} }
} }
Some(path) => { Some(path) => {
let (wrapper, wrapper_ty) = let (wrapper, wrapper_ty) =
wrap_deserialize_with(ident, params, field.ty, path); wrap_deserialize_with(params, field.ty, path);
quote_block! { quote_block! {
#wrapper #wrapper
_serde::export::Result::map( _serde::export::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer), <#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer),
|__wrapper| #ident::#variant_ident(__wrapper.value)) |__wrapper| #this::#variant_ident(__wrapper.value))
} }
} }
} }
@@ -1197,14 +1274,13 @@ fn deserialize_field_visitor(fields: Vec<(String, Ident)>,
} }
} }
_serde::Deserializer::deserialize_struct_field(__deserializer, __FieldVisitor) _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
} }
} }
} }
} }
fn deserialize_struct_visitor(ident: &syn::Ident, fn deserialize_struct_visitor(struct_path: Tokens,
struct_path: Tokens,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item) item_attrs: &attr::Item)
@@ -1224,13 +1300,12 @@ fn deserialize_struct_visitor(ident: &syn::Ident,
let field_visitor = deserialize_field_visitor(field_names_idents, item_attrs, false); let field_visitor = deserialize_field_visitor(field_names_idents, item_attrs, false);
let visit_map = deserialize_map(ident, struct_path, params, fields, item_attrs); let visit_map = deserialize_map(struct_path, params, fields, item_attrs);
(field_visitor, fields_stmt, visit_map) (field_visitor, fields_stmt, visit_map)
} }
fn deserialize_map(ident: &syn::Ident, fn deserialize_map(struct_path: Tokens,
struct_path: Tokens,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item) item_attrs: &attr::Item)
@@ -1266,7 +1341,7 @@ fn deserialize_map(ident: &syn::Ident,
} }
Some(path) => { Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_with( let (wrapper, wrapper_ty) = wrap_deserialize_with(
ident, params, field.ty, path); params, field.ty, path);
quote!({ quote!({
#wrapper #wrapper
try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut __visitor)).value try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut __visitor)).value
@@ -1354,6 +1429,14 @@ fn deserialize_map(ident: &syn::Ident,
} }
}; };
let mut result = quote!(#struct_path { #(#result),* });
if params.has_getter {
let this = &params.this;
result = quote! {
_serde::export::Into::<#this>::into(#result)
};
}
quote_block! { quote_block! {
#(#let_values)* #(#let_values)*
@@ -1363,7 +1446,7 @@ fn deserialize_map(ident: &syn::Ident,
#(#extract_values)* #(#extract_values)*
_serde::export::Ok(#struct_path { #(#result),* }) _serde::export::Ok(#result)
} }
} }
@@ -1373,17 +1456,17 @@ fn field_i(i: usize) -> Ident {
/// This function wraps the expression in `#[serde(deserialize_with = "...")]` /// This function wraps the expression in `#[serde(deserialize_with = "...")]`
/// in a trait to prevent it from accessing the internal `Deserialize` state. /// in a trait to prevent it from accessing the internal `Deserialize` state.
fn wrap_deserialize_with(ident: &syn::Ident, fn wrap_deserialize_with(params: &Parameters,
params: &Parameters,
field_ty: &syn::Ty, field_ty: &syn::Ty,
deserialize_with: &syn::Path) deserialize_with: &syn::Path)
-> (Tokens, Tokens) { -> (Tokens, Tokens) {
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
let wrapper = quote! { let wrapper = quote! {
struct __DeserializeWith #de_impl_generics #where_clause { struct __DeserializeWith #de_impl_generics #where_clause {
value: #field_ty, value: #field_ty,
phantom: _serde::export::PhantomData<#ident #ty_generics>, phantom: _serde::export::PhantomData<#this #ty_generics>,
lifetime: _serde::export::PhantomData<&'de ()>, lifetime: _serde::export::PhantomData<&'de ()>,
} }
@@ -1444,11 +1527,7 @@ struct DeImplGenerics<'a>(&'a Parameters);
impl<'a> ToTokens for DeImplGenerics<'a> { impl<'a> ToTokens for DeImplGenerics<'a> {
fn to_tokens(&self, tokens: &mut Tokens) { fn to_tokens(&self, tokens: &mut Tokens) {
let mut generics = self.0.generics.clone(); let mut generics = self.0.generics.clone();
generics.lifetimes.insert(0, syn::LifetimeDef { generics.lifetimes.insert(0, self.0.de_lifetime_def());
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de"),
bounds: self.0.borrowed.iter().cloned().collect(),
});
let (impl_generics, _, _) = generics.split_for_impl(); let (impl_generics, _, _) = generics.split_for_impl();
impl_generics.to_tokens(tokens); impl_generics.to_tokens(tokens);
} }
+185 -111
View File
@@ -6,21 +6,31 @@ use fragment::{Fragment, Stmts, Match};
use internals::ast::{Body, Field, Item, Style, Variant}; use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{self, attr}; use internals::{self, attr};
use std::u32;
pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String> { pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new(); let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item); let item = Item::from_ast(&ctxt, item);
try!(ctxt.check()); try!(ctxt.check());
let ident = &item.ident; let ident = &item.ident;
let generics = build_generics(&item); let params = Parameters::new(&item);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident)); let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
let body = Stmts(serialize_body(&item, &generics)); let body = Stmts(serialize_body(&item, &params));
Ok(quote! { let impl_item = if let Some(remote) = item.attrs.remote() {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] quote! {
const #dummy_const: () = { impl #impl_generics #ident #ty_generics #where_clause {
extern crate serde as _serde; fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
{
#body
}
}
}
} else {
quote! {
#[automatically_derived] #[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause { impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
@@ -29,10 +39,66 @@ pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String
#body #body
} }
} }
}
};
Ok(quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
extern crate serde as _serde;
#impl_item
}; };
}) })
} }
struct Parameters {
/// Variable holding the value being serialized. Either `self` for local
/// types or `__self` for remote types.
self_var: Ident,
/// Path to the type the impl is for. Either a single `Ident` for local
/// types or `some::remote::Ident` for remote types. Does not include
/// generic parameters.
this: syn::Path,
/// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics,
/// Type has a `serde(remote = "...")` attribute.
is_remote: bool,
}
impl Parameters {
fn new(item: &Item) -> Self {
let is_remote = item.attrs.remote().is_some();
let self_var = if is_remote {
Ident::new("__self")
} else {
Ident::new("self")
};
let this = match item.attrs.remote() {
Some(remote) => remote.clone(),
None => item.ident.clone().into(),
};
let generics = build_generics(item);
Parameters {
self_var: self_var,
this: this,
generics: generics,
is_remote: is_remote,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> &str {
self.this.segments.last().unwrap().ident.as_ref()
}
}
// All the generics in the input, plus a bound `T: Serialize` for each generic // All the generics in the input, plus a bound `T: Serialize` for each generic
// field type that will be serialized by us. // field type that will be serialized by us.
fn build_generics(item: &Item) -> syn::Generics { fn build_generics(item: &Item) -> syn::Generics {
@@ -60,38 +126,39 @@ fn needs_serialize_bound(attrs: &attr::Field) -> bool {
!attrs.skip_serializing() && attrs.serialize_with().is_none() && attrs.ser_bound().is_none() !attrs.skip_serializing() && attrs.serialize_with().is_none() && attrs.ser_bound().is_none()
} }
fn serialize_body(item: &Item, generics: &syn::Generics) -> Fragment { fn serialize_body(item: &Item, params: &Parameters) -> Fragment {
if let Some(into_type) = item.attrs.into_type() { if let Some(into_type) = item.attrs.into_type() {
serialize_into(into_type) serialize_into(params, into_type)
} else { } else {
match item.body { match item.body {
Body::Enum(ref variants) => { Body::Enum(ref variants) => {
serialize_item_enum(&item.ident, generics, variants, &item.attrs) serialize_item_enum(params, variants, &item.attrs)
} }
Body::Struct(Style::Struct, ref fields) => { Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) { if fields.iter().any(|field| field.ident.is_none()) {
panic!("struct has unnamed fields"); panic!("struct has unnamed fields");
} }
serialize_struct(&item.ident, generics, fields, &item.attrs) serialize_struct(params, fields, &item.attrs)
} }
Body::Struct(Style::Tuple, ref fields) => { Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) { if fields.iter().any(|field| field.ident.is_some()) {
panic!("tuple struct has named fields"); panic!("tuple struct has named fields");
} }
serialize_tuple_struct(&item.ident, generics, fields, &item.attrs) serialize_tuple_struct(params, fields, &item.attrs)
} }
Body::Struct(Style::Newtype, ref fields) => { Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(&item.ident, generics, &fields[0], &item.attrs) serialize_newtype_struct(params, &fields[0], &item.attrs)
} }
Body::Struct(Style::Unit, _) => serialize_unit_struct(&item.attrs), Body::Struct(Style::Unit, _) => serialize_unit_struct(&item.attrs),
} }
} }
} }
fn serialize_into(into_type: &syn::Ty) -> Fragment { fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment {
let self_var = &params.self_var;
quote_block! { quote_block! {
_serde::Serialize::serialize( _serde::Serialize::serialize(
&<Self as _serde::export::Into<#into_type>>::into(_serde::export::Clone::clone(self)), &_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)),
__serializer) __serializer)
} }
} }
@@ -104,16 +171,15 @@ fn serialize_unit_struct(item_attrs: &attr::Item) -> Fragment {
} }
} }
fn serialize_newtype_struct(ident: &syn::Ident, fn serialize_newtype_struct(params: &Parameters,
generics: &syn::Generics,
field: &Field, field: &Field,
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
let type_name = item_attrs.name().serialize_name(); let type_name = item_attrs.name().serialize_name();
let mut field_expr = quote!(&self.0); let mut field_expr = get_field(params, field, 0);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
} }
quote_expr! { quote_expr! {
@@ -121,15 +187,13 @@ fn serialize_newtype_struct(ident: &syn::Ident,
} }
} }
fn serialize_tuple_struct(ident: &syn::Ident, fn serialize_tuple_struct(params: &Parameters,
generics: &syn::Generics,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
let serialize_stmts = let serialize_stmts =
serialize_tuple_struct_visitor(ident, serialize_tuple_struct_visitor(fields,
fields, params,
generics,
false, false,
quote!(_serde::ser::SerializeTupleStruct::serialize_field)); quote!(_serde::ser::SerializeTupleStruct::serialize_field));
@@ -144,15 +208,15 @@ fn serialize_tuple_struct(ident: &syn::Ident,
} }
} }
fn serialize_struct(ident: &syn::Ident, fn serialize_struct(params: &Parameters,
generics: &syn::Generics,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
assert!(fields.len() as u64 <= u32::MAX as u64);
let serialize_fields = let serialize_fields =
serialize_struct_visitor(ident, serialize_struct_visitor(fields,
fields, params,
generics,
false, false,
quote!(_serde::ser::SerializeStruct::serialize_field)); quote!(_serde::ser::SerializeStruct::serialize_field));
@@ -165,12 +229,13 @@ fn serialize_struct(ident: &syn::Ident,
let let_mut = mut_if(serialized_fields.peek().is_some()); let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields.map(|field| { let len = serialized_fields.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = quote!(&self.#ident);
match field.attrs.skip_serializing_if() { match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#field_expr) { 0 } else { 1 }),
None => quote!(1), None => quote!(1),
Some(path) => {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = get_field(params, field, ident);
quote!(if #path(#field_expr) { 0 } else { 1 })
}
} }
}) })
.fold(quote!(0), |sum, expr| quote!(#sum + #expr)); .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
@@ -182,40 +247,42 @@ fn serialize_struct(ident: &syn::Ident,
} }
} }
fn serialize_item_enum(ident: &syn::Ident, fn serialize_item_enum(params: &Parameters,
generics: &syn::Generics,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
assert!(variants.len() as u64 <= u32::MAX as u64);
let self_var = &params.self_var;
let arms: Vec<_> = variants.iter() let arms: Vec<_> = variants.iter()
.enumerate() .enumerate()
.map(|(variant_index, variant)| { .map(|(variant_index, variant)| {
serialize_variant(ident, serialize_variant(params,
generics,
variant, variant,
variant_index, variant_index as u32,
item_attrs) item_attrs)
}) })
.collect(); .collect();
quote_expr! { quote_expr! {
match *self { match *#self_var {
#(#arms)* #(#arms)*
} }
} }
} }
fn serialize_variant(ident: &syn::Ident, fn serialize_variant(params: &Parameters,
generics: &syn::Generics,
variant: &Variant, variant: &Variant,
variant_index: usize, variant_index: u32,
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Tokens { -> Tokens {
let this = &params.this;
let variant_ident = variant.ident.clone(); let variant_ident = variant.ident.clone();
if variant.attrs.skip_serializing() { if variant.attrs.skip_serializing() {
let skipped_msg = format!("the enum variant {}::{} cannot be serialized", let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
ident, variant_ident); params.type_name(), variant_ident);
let skipped_err = quote! { let skipped_err = quote! {
_serde::export::Err(_serde::ser::Error::custom(#skipped_msg)) _serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
}; };
@@ -225,26 +292,26 @@ fn serialize_variant(ident: &syn::Ident,
Style::Struct => quote!( {..} ), Style::Struct => quote!( {..} ),
}; };
quote! { quote! {
#ident::#variant_ident #fields_pat => #skipped_err, #this::#variant_ident #fields_pat => #skipped_err,
} }
} else { } else {
// variant wasn't skipped // variant wasn't skipped
let case = match variant.style { let case = match variant.style {
Style::Unit => { Style::Unit => {
quote! { quote! {
#ident::#variant_ident #this::#variant_ident
} }
} }
Style::Newtype => { Style::Newtype => {
quote! { quote! {
#ident::#variant_ident(ref __field0) #this::#variant_ident(ref __field0)
} }
} }
Style::Tuple => { Style::Tuple => {
let field_names = (0..variant.fields.len()) let field_names = (0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i))); .map(|i| Ident::new(format!("__field{}", i)));
quote! { quote! {
#ident::#variant_ident(#(ref #field_names),*) #this::#variant_ident(#(ref #field_names),*)
} }
} }
Style::Struct => { Style::Struct => {
@@ -252,35 +319,32 @@ fn serialize_variant(ident: &syn::Ident,
.iter() .iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields")); .map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
quote! { quote! {
#ident::#variant_ident { #(ref #fields),* } #this::#variant_ident { #(ref #fields),* }
} }
} }
}; };
let body = Match(match *item_attrs.tag() { let body = Match(match *item_attrs.tag() {
attr::EnumTag::External => { attr::EnumTag::External => {
serialize_externally_tagged_variant(ident, serialize_externally_tagged_variant(params,
generics,
variant, variant,
variant_index, variant_index,
item_attrs) item_attrs)
} }
attr::EnumTag::Internal { ref tag } => { attr::EnumTag::Internal { ref tag } => {
serialize_internally_tagged_variant(ident, serialize_internally_tagged_variant(params,
generics,
variant, variant,
item_attrs, item_attrs,
tag) tag)
} }
attr::EnumTag::Adjacent { ref tag, ref content } => { attr::EnumTag::Adjacent { ref tag, ref content } => {
serialize_adjacently_tagged_variant(ident, serialize_adjacently_tagged_variant(params,
generics,
variant, variant,
item_attrs, item_attrs,
tag, tag,
content) content)
} }
attr::EnumTag::None => serialize_untagged_variant(ident, generics, variant, item_attrs), attr::EnumTag::None => serialize_untagged_variant(params, variant, item_attrs),
}); });
quote! { quote! {
@@ -289,10 +353,9 @@ fn serialize_variant(ident: &syn::Ident,
} }
} }
fn serialize_externally_tagged_variant(ident: &syn::Ident, fn serialize_externally_tagged_variant(params: &Parameters,
generics: &syn::Generics,
variant: &Variant, variant: &Variant,
variant_index: usize, variant_index: u32,
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
let type_name = item_attrs.name().serialize_name(); let type_name = item_attrs.name().serialize_name();
@@ -313,7 +376,7 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
let field = &variant.fields[0]; let field = &variant.fields[0];
let mut field_expr = quote!(__field0); let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
} }
quote_expr! { quote_expr! {
@@ -332,8 +395,7 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
variant_index: variant_index, variant_index: variant_index,
variant_name: variant_name, variant_name: variant_name,
}, },
ident, params,
generics,
&variant.fields) &variant.fields)
} }
Style::Struct => { Style::Struct => {
@@ -341,16 +403,14 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
variant_index: variant_index, variant_index: variant_index,
variant_name: variant_name, variant_name: variant_name,
}, },
ident, params,
generics,
&variant.fields, &variant.fields,
&type_name) &type_name)
} }
} }
} }
fn serialize_internally_tagged_variant(ident: &syn::Ident, fn serialize_internally_tagged_variant(params: &Parameters,
generics: &syn::Generics,
variant: &Variant, variant: &Variant,
item_attrs: &attr::Item, item_attrs: &attr::Item,
tag: &str) tag: &str)
@@ -358,7 +418,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
let type_name = item_attrs.name().serialize_name(); let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
let enum_ident_str = ident.as_ref(); let enum_ident_str = params.type_name();
let variant_ident_str = variant.ident.as_ref(); let variant_ident_str = variant.ident.as_ref();
match variant.style { match variant.style {
@@ -375,7 +435,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
let field = &variant.fields[0]; let field = &variant.fields[0];
let mut field_expr = quote!(__field0); let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
} }
quote_expr! { quote_expr! {
@@ -394,8 +454,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
tag: tag, tag: tag,
variant_name: variant_name, variant_name: variant_name,
}, },
ident, params,
generics,
&variant.fields, &variant.fields,
&type_name) &type_name)
} }
@@ -403,13 +462,13 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
} }
} }
fn serialize_adjacently_tagged_variant(ident: &syn::Ident, fn serialize_adjacently_tagged_variant(params: &Parameters,
generics: &syn::Generics,
variant: &Variant, variant: &Variant,
item_attrs: &attr::Item, item_attrs: &attr::Item,
tag: &str, tag: &str,
content: &str) content: &str)
-> Fragment { -> Fragment {
let this = &params.this;
let type_name = item_attrs.name().serialize_name(); let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
@@ -427,7 +486,7 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
let field = &variant.fields[0]; let field = &variant.fields[0];
let mut field_expr = quote!(__field0); let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
} }
quote_expr! { quote_expr! {
@@ -436,14 +495,12 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
} }
Style::Tuple => { Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, serialize_tuple_variant(TupleVariant::Untagged,
ident, params,
generics,
&variant.fields) &variant.fields)
} }
Style::Struct => { Style::Struct => {
serialize_struct_variant(StructVariant::Untagged, serialize_struct_variant(StructVariant::Untagged,
ident, params,
generics,
&variant.fields, &variant.fields,
&variant_name) &variant_name)
} }
@@ -466,15 +523,15 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
} }
}; };
let (_, ty_generics, where_clause) = generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(generics, "'__a"); let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote_block! { quote_block! {
struct __AdjacentlyTagged #wrapper_generics #where_clause { struct __AdjacentlyTagged #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*), data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#ident #ty_generics>, phantom: _serde::export::PhantomData<#this #ty_generics>,
} }
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
@@ -493,14 +550,13 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
try!(_serde::ser::SerializeStruct::serialize_field( try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged { &mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*), data: (#(#fields_ident,)*),
phantom: _serde::export::PhantomData::<#ident #ty_generics>, phantom: _serde::export::PhantomData::<#this #ty_generics>,
})); }));
_serde::ser::SerializeStruct::end(__struct) _serde::ser::SerializeStruct::end(__struct)
} }
} }
fn serialize_untagged_variant(ident: &syn::Ident, fn serialize_untagged_variant(params: &Parameters,
generics: &syn::Generics,
variant: &Variant, variant: &Variant,
item_attrs: &attr::Item) item_attrs: &attr::Item)
-> Fragment { -> Fragment {
@@ -514,7 +570,7 @@ fn serialize_untagged_variant(ident: &syn::Ident,
let field = &variant.fields[0]; let field = &variant.fields[0];
let mut field_expr = quote!(__field0); let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(ident, generics, field.ty, path, field_expr); field_expr = wrap_serialize_with(params, field.ty, path, field_expr);
} }
quote_expr! { quote_expr! {
@@ -522,13 +578,12 @@ fn serialize_untagged_variant(ident: &syn::Ident,
} }
} }
Style::Tuple => { Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, ident, generics, &variant.fields) serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
} }
Style::Struct => { Style::Struct => {
let type_name = item_attrs.name().serialize_name(); let type_name = item_attrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged, serialize_struct_variant(StructVariant::Untagged,
ident, params,
generics,
&variant.fields, &variant.fields,
&type_name) &type_name)
} }
@@ -538,15 +593,14 @@ fn serialize_untagged_variant(ident: &syn::Ident,
enum TupleVariant { enum TupleVariant {
ExternallyTagged { ExternallyTagged {
type_name: String, type_name: String,
variant_index: usize, variant_index: u32,
variant_name: String, variant_name: String,
}, },
Untagged, Untagged,
} }
fn serialize_tuple_variant(context: TupleVariant, fn serialize_tuple_variant(context: TupleVariant,
ident: &syn::Ident, params: &Parameters,
generics: &syn::Generics,
fields: &[Field]) fields: &[Field])
-> Fragment { -> Fragment {
let method = match context { let method = match context {
@@ -557,7 +611,7 @@ fn serialize_tuple_variant(context: TupleVariant,
}; };
let serialize_stmts = let serialize_stmts =
serialize_tuple_struct_visitor(ident, fields, generics, true, method); serialize_tuple_struct_visitor(fields, params, true, method);
let len = serialize_stmts.len(); let len = serialize_stmts.len();
let let_mut = mut_if(len > 0); let let_mut = mut_if(len > 0);
@@ -589,7 +643,7 @@ fn serialize_tuple_variant(context: TupleVariant,
enum StructVariant<'a> { enum StructVariant<'a> {
ExternallyTagged { ExternallyTagged {
variant_index: usize, variant_index: u32,
variant_name: String, variant_name: String,
}, },
InternallyTagged { tag: &'a str, variant_name: String }, InternallyTagged { tag: &'a str, variant_name: String },
@@ -597,8 +651,7 @@ enum StructVariant<'a> {
} }
fn serialize_struct_variant<'a>(context: StructVariant<'a>, fn serialize_struct_variant<'a>(context: StructVariant<'a>,
ident: &syn::Ident, params: &Parameters,
generics: &syn::Generics,
fields: &[Field], fields: &[Field],
name: &str) name: &str)
-> Fragment { -> Fragment {
@@ -610,7 +663,7 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>,
StructVariant::Untagged => quote!(_serde::ser::SerializeStruct::serialize_field), StructVariant::Untagged => quote!(_serde::ser::SerializeStruct::serialize_field),
}; };
let serialize_fields = serialize_struct_visitor(ident, fields, generics, true, method); let serialize_fields = serialize_struct_visitor(fields, params, true, method);
let mut serialized_fields = fields.iter() let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
@@ -672,9 +725,8 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>,
} }
} }
fn serialize_tuple_struct_visitor(ident: &syn::Ident, fn serialize_tuple_struct_visitor(fields: &[Field],
fields: &[Field], params: &Parameters,
generics: &syn::Generics,
is_enum: bool, is_enum: bool,
func: Tokens) func: Tokens)
-> Vec<Tokens> { -> Vec<Tokens> {
@@ -685,8 +737,7 @@ fn serialize_tuple_struct_visitor(ident: &syn::Ident,
let id = Ident::new(format!("__field{}", i)); let id = Ident::new(format!("__field{}", i));
quote!(#id) quote!(#id)
} else { } else {
let i = Ident::new(i); get_field(params, field, i)
quote!(&self.#i)
}; };
let skip = field.attrs let skip = field.attrs
@@ -695,7 +746,7 @@ fn serialize_tuple_struct_visitor(ident: &syn::Ident,
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = field_expr =
wrap_serialize_with(ident, generics, field.ty, path, field_expr); wrap_serialize_with(params, field.ty, path, field_expr);
} }
let ser = quote! { let ser = quote! {
@@ -710,9 +761,8 @@ fn serialize_tuple_struct_visitor(ident: &syn::Ident,
.collect() .collect()
} }
fn serialize_struct_visitor(ident: &syn::Ident, fn serialize_struct_visitor(fields: &[Field],
fields: &[Field], params: &Parameters,
generics: &syn::Generics,
is_enum: bool, is_enum: bool,
func: Tokens) func: Tokens)
-> Vec<Tokens> { -> Vec<Tokens> {
@@ -723,7 +773,7 @@ fn serialize_struct_visitor(ident: &syn::Ident,
let mut field_expr = if is_enum { let mut field_expr = if is_enum {
quote!(#field_ident) quote!(#field_ident)
} else { } else {
quote!(&self.#field_ident) get_field(params, field, field_ident)
}; };
let key_expr = field.attrs.name().serialize_name(); let key_expr = field.attrs.name().serialize_name();
@@ -734,7 +784,7 @@ fn serialize_struct_visitor(ident: &syn::Ident,
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = field_expr =
wrap_serialize_with(ident, generics, field.ty, path, field_expr) wrap_serialize_with(params, field.ty, path, field_expr)
} }
let ser = quote! { let ser = quote! {
@@ -749,21 +799,21 @@ fn serialize_struct_visitor(ident: &syn::Ident,
.collect() .collect()
} }
fn wrap_serialize_with(ident: &syn::Ident, fn wrap_serialize_with(params: &Parameters,
generics: &syn::Generics,
field_ty: &syn::Ty, field_ty: &syn::Ty,
serialize_with: &syn::Path, serialize_with: &syn::Path,
value: Tokens) value: Tokens)
-> Tokens { -> Tokens {
let (_, ty_generics, where_clause) = generics.split_for_impl(); let this = &params.this;
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(generics, "'__a"); let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote!({ quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause { struct __SerializeWith #wrapper_impl_generics #where_clause {
value: &'__a #field_ty, value: &'__a #field_ty,
phantom: _serde::export::PhantomData<#ident #ty_generics>, phantom: _serde::export::PhantomData<#this #ty_generics>,
} }
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
@@ -776,7 +826,7 @@ fn wrap_serialize_with(ident: &syn::Ident,
&__SerializeWith { &__SerializeWith {
value: #value, value: #value,
phantom: _serde::export::PhantomData::<#ident #ty_generics>, phantom: _serde::export::PhantomData::<#this #ty_generics>,
} }
}) })
} }
@@ -790,3 +840,27 @@ fn wrap_serialize_with(ident: &syn::Ident,
fn mut_if(is_mut: bool) -> Option<Tokens> { fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut { Some(quote!(mut)) } else { None } if is_mut { Some(quote!(mut)) } else { None }
} }
fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
where I: Into<Ident>
{
let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => {
let ident = ident.into();
quote!(&#self_var.#ident)
}
(true, None) => {
let ty = field.ty;
let ident = ident.into();
quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident))
}
(true, Some(getter)) => {
let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(&#getter(#self_var)))
}
(false, Some(_)) => {
unreachable!("getter is only allowed for remote impls");
}
}
}
+2 -2
View File
@@ -78,7 +78,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
seq bytes byte_buf map struct_field ignored_any seq bytes byte_buf map identifier ignored_any
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
@@ -645,6 +645,6 @@ impl<'de> de::Deserializer<'de> for BytesDeserializer {
forward_to_deserialize! { forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
struct struct_field tuple enum ignored_any byte_buf struct identifier tuple enum ignored_any byte_buf
} }
} }
+4 -4
View File
@@ -146,7 +146,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
fn serialize_unit_variant(self, fn serialize_unit_variant(self,
name: &'static str, name: &'static str,
_variant_index: usize, _variant_index: u32,
variant: &'static str) variant: &'static str)
-> Result<(), Error> { -> Result<(), Error> {
if self.tokens.first() == Some(&Token::Enum(name)) { if self.tokens.first() == Some(&Token::Enum(name)) {
@@ -168,7 +168,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
fn serialize_newtype_variant<T: ?Sized>(self, fn serialize_newtype_variant<T: ?Sized>(self,
name: &'static str, name: &'static str,
_variant_index: usize, _variant_index: u32,
variant: &'static str, variant: &'static str,
value: &T) value: &T)
-> Result<(), Error> -> Result<(), Error>
@@ -217,7 +217,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
fn serialize_tuple_variant(self, fn serialize_tuple_variant(self,
name: &'static str, name: &'static str,
_variant_index: usize, _variant_index: u32,
variant: &'static str, variant: &'static str,
len: usize) len: usize)
-> Result<Self, Error> { -> Result<Self, Error> {
@@ -237,7 +237,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
fn serialize_struct_variant(self, fn serialize_struct_variant(self,
name: &'static str, name: &'static str,
_variant_index: usize, _variant_index: u32,
variant: &'static str, variant: &'static str,
len: usize) len: usize)
-> Result<Self, Error> { -> Result<Self, Error> {
@@ -0,0 +1,17 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "remote::S")]
struct S {
#[serde(getter = "~~~")] //~^^^ HELP: failed to parse path: "~~~"
a: u8,
}
fn main() {}
@@ -0,0 +1,16 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "~~~")] //~^ HELP: failed to parse path: "~~~"
struct S {
a: u8,
}
fn main() {}
@@ -0,0 +1,19 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub enum E {
A { a: u8 }
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "remote::E")]
pub enum E {
A {
#[serde(getter = "get_a")] //~^^^^ HELP: #[serde(getter = "...")] is not allowed in an enum
a: u8,
}
}
fn main() {}
@@ -0,0 +1,17 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u8,
pub b: u8,
}
}
#[derive(Serialize, Deserialize)] //~ ERROR: missing field `b` in initializer of `remote::S`
#[serde(remote = "remote::S")]
struct S {
a: u8, //~^^^ ERROR: missing field `b` in initializer of `remote::S`
}
fn main() {}
@@ -0,0 +1,16 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(getter = "S::get")] //~^^ HELP: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")]
a: u8,
}
impl S {
fn get(&self) -> u8 {
self.a
}
}
fn main() {}
@@ -0,0 +1,16 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u8,
}
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")]
struct S {
b: u8, //~^^^ ERROR: no field `b` on type `&remote::S`
}
fn main() {}
@@ -0,0 +1,12 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S(pub u16);
}
#[derive(Deserialize)] //~ ERROR: mismatched types
#[serde(remote = "remote::S")]
struct S(u8); //~^^ expected u16, found u8
fn main() {}
@@ -0,0 +1,23 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
impl S {
pub fn get(&self) -> u16 {
self.a as u16
}
}
}
#[derive(Serialize)] //~ ERROR: mismatched types
#[serde(remote = "remote::S")]
struct S {
#[serde(getter = "remote::S::get")]
a: u8, //~^^^^ expected u8, found u16
}
fn main() {}
@@ -0,0 +1,16 @@
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u16,
}
}
#[derive(Serialize)] //~ ERROR: mismatched types
#[serde(remote = "remote::S")]
struct S {
a: u8, //~^^^ expected u8, found u16
}
fn main() {}
+7 -8
View File
@@ -242,14 +242,6 @@ declare_tests! {
UnitStruct => &[ UnitStruct => &[
Token::UnitStruct("UnitStruct"), Token::UnitStruct("UnitStruct"),
], ],
UnitStruct => &[
Token::Seq(Some(0)),
Token::SeqEnd,
],
UnitStruct => &[
Token::Seq(None),
Token::SeqEnd,
],
} }
test_newtype_struct { test_newtype_struct {
NewtypeStruct(1) => &[ NewtypeStruct(1) => &[
@@ -1036,4 +1028,11 @@ declare_error_tests! {
], ],
Error::Message("invalid type: floating point `0`, expected isize".into()), Error::Message("invalid type: floating point `0`, expected isize".into()),
} }
test_unit_struct_from_seq<UnitStruct> {
&[
Token::Seq(Some(0)),
Token::SeqEnd,
],
Error::Message("invalid type: sequence, expected unit struct UnitStruct".into()),
}
} }
+184
View File
@@ -0,0 +1,184 @@
#[macro_use]
extern crate serde_derive;
extern crate serde;
mod remote {
pub struct Unit;
pub struct PrimitivePriv(u8);
pub struct PrimitivePub(pub u8);
pub struct NewtypePriv(Unit);
pub struct NewtypePub(pub Unit);
pub struct TuplePriv(u8, Unit);
pub struct TuplePub(pub u8, pub Unit);
pub struct StructPriv {
a: u8,
b: Unit,
}
pub struct StructPub {
pub a: u8,
pub b: Unit,
}
impl PrimitivePriv {
pub fn new(a: u8) -> Self {
PrimitivePriv(a)
}
pub fn get(&self) -> u8 {
self.0
}
}
impl NewtypePriv {
pub fn new(a: Unit) -> Self {
NewtypePriv(a)
}
pub fn get(&self) -> &Unit {
&self.0
}
}
impl TuplePriv {
pub fn new(a: u8, b: Unit) -> Self {
TuplePriv(a, b)
}
pub fn first(&self) -> u8 {
self.0
}
pub fn second(&self) -> &Unit {
&self.1
}
}
impl StructPriv {
pub fn new(a: u8, b: Unit) -> Self {
StructPriv { a: a, b: b }
}
pub fn a(&self) -> u8 {
self.a
}
pub fn b(&self) -> &Unit {
&self.b
}
}
}
#[derive(Serialize, Deserialize)]
struct Test {
#[serde(with = "UnitDef")]
unit: remote::Unit,
#[serde(with = "PrimitivePrivDef")]
primitive_priv: remote::PrimitivePriv,
#[serde(with = "PrimitivePubDef")]
primitive_pub: remote::PrimitivePub,
#[serde(with = "NewtypePrivDef")]
newtype_priv: remote::NewtypePriv,
#[serde(with = "NewtypePubDef")]
newtype_pub: remote::NewtypePub,
#[serde(with = "TuplePrivDef")]
tuple_priv: remote::TuplePriv,
#[serde(with = "TuplePubDef")]
tuple_pub: remote::TuplePub,
#[serde(with = "StructPrivDef")]
struct_priv: remote::StructPriv,
#[serde(with = "StructPubDef")]
struct_pub: remote::StructPub,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::Unit")]
struct UnitDef;
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePriv")]
struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePub")]
struct PrimitivePubDef(u8);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePriv")]
struct NewtypePrivDef(#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePub")]
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePriv")]
struct TuplePrivDef(
#[serde(getter = "remote::TuplePriv::first")] u8,
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePub")]
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPriv")]
struct StructPrivDef {
#[serde(getter = "remote::StructPriv::a")]
a: u8,
#[serde(getter = "remote::StructPriv::b")]
#[serde(with= "UnitDef")]
b: remote::Unit,
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPub")]
struct StructPubDef {
#[allow(dead_code)]
a: u8,
#[allow(dead_code)]
#[serde(with= "UnitDef")]
b: remote::Unit,
}
impl From<PrimitivePrivDef> for remote::PrimitivePriv {
fn from(def: PrimitivePrivDef) -> Self {
remote::PrimitivePriv::new(def.0)
}
}
impl From<NewtypePrivDef> for remote::NewtypePriv {
fn from(def: NewtypePrivDef) -> Self {
remote::NewtypePriv::new(def.0)
}
}
impl From<TuplePrivDef> for remote::TuplePriv {
fn from(def: TuplePrivDef) -> Self {
remote::TuplePriv::new(def.0, def.1)
}
}
impl From<StructPrivDef> for remote::StructPriv {
fn from(def: StructPrivDef) -> Self {
remote::StructPriv::new(def.a, def.b)
}
}
+3 -1
View File
@@ -4,10 +4,12 @@ extern crate serde_derive;
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
use std::net; use std::net;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str;
use std::time::Duration; use std::time::Duration;
use std::ffi::CString; use std::ffi::CString;
#[cfg(unix)]
use std::str;
extern crate serde; extern crate serde;
extern crate serde_test; extern crate serde_test;