Merge branch 'origin/1.0' into 'origin/fwd'
Conflicts: serde/src/macros.rs
This commit is contained in:
commit
b40ecf04ce
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -911,8 +911,8 @@ pub trait Deserializer<'de>: Sized {
|
||||
where V: Visitor<'de>;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting the name of a struct
|
||||
/// field.
|
||||
fn deserialize_struct_field<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
/// field or the discriminant of an enum variant.
|
||||
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor<'de>;
|
||||
|
||||
/// Hint that the `Deserialize` type is expecting an enum value with a
|
||||
|
@ -108,7 +108,7 @@ impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
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>
|
||||
@ -155,7 +155,7 @@ macro_rules! primitive_deserializer {
|
||||
forward_to_deserialize! {
|
||||
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 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>
|
||||
@ -208,7 +208,7 @@ impl<'de, E> de::Deserializer<'de> for U32Deserializer<E>
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
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>
|
||||
@ -286,7 +286,7 @@ impl<'de, 'a, E> de::Deserializer<'de> for StrDeserializer<'a, E>
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -804,7 +804,7 @@ impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer<A, B, E>
|
||||
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
}
|
||||
|
||||
@ -945,7 +945,7 @@ impl<'de, V_> de::Deserializer<'de> for MapVisitorDeserializer<V_>
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
struct struct_field tuple enum ignored_any byte_buf
|
||||
struct identifier tuple enum ignored_any byte_buf
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,8 @@ macro_rules! forward_to_deserialize_helper {
|
||||
(struct<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
|
||||
};
|
||||
(struct_field<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_method!{deserialize_struct_field<$l, $v>()}
|
||||
(identifier<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_method!{deserialize_identifier<$l, $v>()}
|
||||
};
|
||||
(tuple<$l:tt, $v:ident>) => {
|
||||
forward_to_deserialize_method!{deserialize_tuple<$l, $v>(len: usize)}
|
||||
@ -146,7 +146,7 @@ macro_rules! forward_to_deserialize_helper {
|
||||
/// # forward_to_deserialize! {
|
||||
/// # 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
|
||||
/// # 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! {
|
||||
/// 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
|
||||
/// 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>>
|
||||
/// 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
|
||||
/// tuple_struct struct struct_field tuple enum ignored_any
|
||||
/// tuple_struct struct identifier tuple enum ignored_any
|
||||
/// }
|
||||
/// # }
|
||||
/// #
|
||||
|
@ -52,7 +52,7 @@ pub fn missing_field<'de, V, E>(field: &'static str) -> Result<V, E>
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
struct_field tuple ignored_any
|
||||
identifier tuple ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
@ -996,7 +996,7 @@ mod content {
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
struct_field tuple ignored_any
|
||||
identifier tuple ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
@ -1341,7 +1341,7 @@ mod content {
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
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! {
|
||||
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
|
||||
tuple_struct struct struct_field tuple enum ignored_any
|
||||
tuple_struct struct identifier tuple enum ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,13 +66,13 @@ macro_rules! __serialize_unimplemented_helper {
|
||||
__serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok);
|
||||
};
|
||||
(unit_variant) => {
|
||||
__serialize_unimplemented_method!(serialize_unit_variant(&str, usize, &str) -> Ok);
|
||||
__serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok);
|
||||
};
|
||||
(newtype_struct) => {
|
||||
__serialize_unimplemented_method!(serialize_newtype_struct<T>(&str, &T) -> Ok);
|
||||
};
|
||||
(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) => {
|
||||
type SerializeSeq = $crate::ser::Impossible<Self::Ok, Self::Error>;
|
||||
@ -91,7 +91,7 @@ macro_rules! __serialize_unimplemented_helper {
|
||||
};
|
||||
(tuple_variant) => {
|
||||
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) => {
|
||||
type SerializeMap = $crate::ser::Impossible<Self::Ok, Self::Error>;
|
||||
@ -103,7 +103,7 @@ macro_rules! __serialize_unimplemented_helper {
|
||||
};
|
||||
(struct_variant) => {
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,12 @@ use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMap
|
||||
#[cfg(feature = "std")]
|
||||
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.
|
||||
pub fn serialize_tagged_newtype<S, T>(serializer: S,
|
||||
type_ident: &'static str,
|
||||
@ -184,7 +190,7 @@ impl<S> Serializer for TaggedSerializer<S>
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: u32,
|
||||
inner_variant: &'static str)
|
||||
-> Result<Self::Ok, Self::Error> {
|
||||
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,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: u32,
|
||||
inner_variant: &'static str,
|
||||
inner_value: &T)
|
||||
-> Result<Self::Ok, Self::Error>
|
||||
@ -238,7 +244,7 @@ impl<S> Serializer for TaggedSerializer<S>
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
fn serialize_tuple_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
_: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
@ -250,7 +256,7 @@ impl<S> Serializer for TaggedSerializer<S>
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn serialize_tuple_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: u32,
|
||||
inner_variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
@ -278,7 +284,7 @@ impl<S> Serializer for TaggedSerializer<S>
|
||||
#[cfg(not(any(feature = "std", feature = "collections")))]
|
||||
fn serialize_struct_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
_: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
@ -290,7 +296,7 @@ impl<S> Serializer for TaggedSerializer<S>
|
||||
#[cfg(any(feature = "std", feature = "collections"))]
|
||||
fn serialize_struct_variant(self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
_: u32,
|
||||
inner_variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
@ -444,18 +450,18 @@ mod content {
|
||||
|
||||
Unit,
|
||||
UnitStruct(&'static str),
|
||||
UnitVariant(&'static str, usize, &'static str),
|
||||
UnitVariant(&'static str, u32, &'static str),
|
||||
NewtypeStruct(&'static str, Box<Content>),
|
||||
NewtypeVariant(&'static str, usize, &'static str, Box<Content>),
|
||||
NewtypeVariant(&'static str, u32, &'static str, Box<Content>),
|
||||
|
||||
Seq(Vec<Content>),
|
||||
SeqFixedSize(Vec<Content>),
|
||||
Tuple(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)>),
|
||||
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 {
|
||||
@ -645,7 +651,7 @@ mod content {
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str)
|
||||
-> Result<Content, E> {
|
||||
Ok(Content::UnitVariant(name, variant_index, variant))
|
||||
@ -660,7 +666,7 @@ mod content {
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T)
|
||||
-> Result<Content, E> {
|
||||
@ -706,7 +712,7 @@ mod content {
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, E> {
|
||||
@ -737,7 +743,7 @@ mod content {
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStructVariant, E> {
|
||||
@ -825,7 +831,7 @@ mod content {
|
||||
|
||||
struct SerializeTupleVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
fields: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
@ -916,7 +922,7 @@ mod content {
|
||||
|
||||
struct SerializeStructVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
error: PhantomData<E>,
|
||||
|
@ -449,7 +449,7 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_unit_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str)
|
||||
-> Result<Self::Ok, Self::Error>;
|
||||
|
||||
@ -504,7 +504,7 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T)
|
||||
-> Result<Self::Ok, Self::Error>;
|
||||
@ -686,7 +686,7 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_tuple_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeTupleVariant, Self::Error>;
|
||||
@ -806,7 +806,7 @@ pub trait Serializer: Sized {
|
||||
/// ```
|
||||
fn serialize_struct_variant(self,
|
||||
name: &'static str,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self::SerializeStructVariant, Self::Error>;
|
||||
|
@ -1,5 +1,6 @@
|
||||
use syn;
|
||||
use attr;
|
||||
use check;
|
||||
use Ctxt;
|
||||
|
||||
pub struct Item<'a> {
|
||||
@ -62,12 +63,14 @@ impl<'a> Item<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
let item = Item {
|
||||
ident: item.ident.clone(),
|
||||
attrs: attrs,
|
||||
body: body,
|
||||
generics: &item.generics,
|
||||
}
|
||||
};
|
||||
check::check(cx, &item);
|
||||
item
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +84,10 @@ impl<'a> Body<'a> {
|
||||
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>> {
|
||||
|
@ -102,6 +102,7 @@ pub struct Item {
|
||||
tag: EnumTag,
|
||||
from_type: Option<syn::Ty>,
|
||||
into_type: Option<syn::Ty>,
|
||||
remote: Option<syn::Path>,
|
||||
}
|
||||
|
||||
/// Styles of representing an enum.
|
||||
@ -151,6 +152,7 @@ impl Item {
|
||||
let mut content = Attr::none(cx, "content");
|
||||
let mut from_type = Attr::none(cx, "from");
|
||||
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_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) => {
|
||||
cx.error(format!("unknown serde container attribute `{}`",
|
||||
meta_item.name()));
|
||||
@ -361,6 +370,7 @@ impl Item {
|
||||
tag: tag,
|
||||
from_type: from_type.get(),
|
||||
into_type: into_type.get(),
|
||||
remote: remote.get(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,6 +409,10 @@ impl Item {
|
||||
pub fn into_type(&self) -> Option<&syn::Ty> {
|
||||
self.into_type.as_ref()
|
||||
}
|
||||
|
||||
pub fn remote(&self) -> Option<&syn::Path> {
|
||||
self.remote.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents variant attribute information
|
||||
@ -531,6 +545,7 @@ pub struct Field {
|
||||
ser_bound: Option<Vec<syn::WherePredicate>>,
|
||||
de_bound: Option<Vec<syn::WherePredicate>>,
|
||||
borrowed_lifetimes: BTreeSet<syn::Lifetime>,
|
||||
getter: Option<syn::Path>,
|
||||
}
|
||||
|
||||
/// 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 de_bound = Attr::none(cx, "bound");
|
||||
let mut borrowed_lifetimes = Attr::none(cx, "borrow");
|
||||
let mut getter = Attr::none(cx, "getter");
|
||||
|
||||
let ident = match field.ident {
|
||||
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) => {
|
||||
cx.error(format!("unknown serde field attribute `{}`", meta_item.name()));
|
||||
}
|
||||
@ -737,6 +760,7 @@ impl Field {
|
||||
ser_bound: ser_bound.get(),
|
||||
de_bound: de_bound.get(),
|
||||
borrowed_lifetimes: borrowed_lifetimes,
|
||||
getter: getter.get(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,6 +812,10 @@ impl Field {
|
||||
pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> {
|
||||
&self.borrowed_lifetimes
|
||||
}
|
||||
|
||||
pub fn getter(&self) -> Option<&syn::Path> {
|
||||
self.getter.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
type SerAndDe<T> = (Option<T>, Option<T>);
|
||||
|
20
serde_codegen_internals/src/check.rs
Normal file
20
serde_codegen_internals/src/check.rs
Normal 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 = \"...\")]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -9,3 +9,4 @@ mod ctxt;
|
||||
pub use ctxt::Ctxt;
|
||||
|
||||
mod case;
|
||||
mod check;
|
||||
|
@ -14,17 +14,25 @@ pub fn expand_derive_deserialize(item: &syn::DeriveInput) -> Result<Tokens, Stri
|
||||
try!(ctxt.check());
|
||||
|
||||
let ident = &item.ident;
|
||||
let generics = build_generics(&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(¶ms);
|
||||
let params = Parameters::new(&item);
|
||||
let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident));
|
||||
let body = Stmts(deserialize_body(&item, ¶ms));
|
||||
|
||||
Ok(quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const #dummy_const: () = {
|
||||
extern crate serde as _serde;
|
||||
let impl_item = if let Some(remote) = item.attrs.remote() {
|
||||
let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
|
||||
let de_lifetime = params.de_lifetime_def();
|
||||
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(¶ms);
|
||||
quote! {
|
||||
#[automatically_derived]
|
||||
impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const #dummy_const: () = {
|
||||
extern crate serde as _serde;
|
||||
#impl_item
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
/// Lifetimes borrowed from the deserializer. These will become bounds on
|
||||
/// the `'de` lifetime of the deserializer.
|
||||
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
|
||||
@ -109,14 +176,13 @@ fn deserialize_body(item: &Item, params: &Parameters) -> Fragment {
|
||||
} else {
|
||||
match item.body {
|
||||
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) => {
|
||||
if fields.iter().any(|field| field.ident.is_none()) {
|
||||
panic!("struct has unnamed fields");
|
||||
}
|
||||
deserialize_struct(&item.ident,
|
||||
None,
|
||||
deserialize_struct(None,
|
||||
params,
|
||||
fields,
|
||||
&item.attrs,
|
||||
@ -127,14 +193,13 @@ fn deserialize_body(item: &Item, params: &Parameters) -> Fragment {
|
||||
if fields.iter().any(|field| field.ident.is_some()) {
|
||||
panic!("tuple struct has named fields");
|
||||
}
|
||||
deserialize_tuple(&item.ident,
|
||||
None,
|
||||
deserialize_tuple(None,
|
||||
params,
|
||||
fields,
|
||||
&item.attrs,
|
||||
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 = ¶ms.this;
|
||||
let type_name = item_attrs.name().deserialize_name();
|
||||
|
||||
let expecting = format!("unit struct {}", ident);
|
||||
let expecting = format!("unit struct {}", params.type_name());
|
||||
|
||||
quote_block! {
|
||||
struct __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 {
|
||||
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
|
||||
}
|
||||
|
||||
#[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
|
||||
{
|
||||
_serde::export::Ok(#ident)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#ident, __V::Error>
|
||||
where __V: _serde::de::SeqVisitor<'de>
|
||||
{
|
||||
_serde::export::Ok(#ident)
|
||||
_serde::export::Ok(#this)
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,38 +240,48 @@ fn deserialize_unit_struct(ident: &syn::Ident, item_attrs: &attr::Item) -> Fragm
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_tuple(ident: &syn::Ident,
|
||||
variant_ident: Option<&syn::Ident>,
|
||||
fn deserialize_tuple(variant_ident: Option<&syn::Ident>,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
item_attrs: &attr::Item,
|
||||
deserializer: Option<Tokens>)
|
||||
-> Fragment {
|
||||
let this = ¶ms.this;
|
||||
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 = ¶ms.local;
|
||||
quote!(#local)
|
||||
} else {
|
||||
quote!(#this)
|
||||
};
|
||||
|
||||
let is_enum = variant_ident.is_some();
|
||||
let type_path = match variant_ident {
|
||||
Some(variant_ident) => quote!(#ident::#variant_ident),
|
||||
None => quote!(#ident),
|
||||
Some(variant_ident) => quote!(#construct::#variant_ident),
|
||||
None => construct,
|
||||
};
|
||||
let expecting = match variant_ident {
|
||||
Some(variant_ident) => format!("tuple variant {}::{}", ident, variant_ident),
|
||||
None => format!("tuple struct {}", ident),
|
||||
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
|
||||
None => format!("tuple struct {}", params.type_name()),
|
||||
};
|
||||
|
||||
let nfields = fields.len();
|
||||
|
||||
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 {
|
||||
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! {
|
||||
__Visitor {
|
||||
marker: _serde::export::PhantomData::<#ident #ty_generics>,
|
||||
marker: _serde::export::PhantomData::<#this #ty_generics>,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
}
|
||||
};
|
||||
@ -237,12 +306,12 @@ fn deserialize_tuple(ident: &syn::Ident,
|
||||
|
||||
quote_block! {
|
||||
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 ()>,
|
||||
}
|
||||
|
||||
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 {
|
||||
_serde::export::fmt::Formatter::write_str(formatter, #expecting)
|
||||
@ -262,8 +331,7 @@ fn deserialize_tuple(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_seq(ident: &syn::Ident,
|
||||
type_path: &Tokens,
|
||||
fn deserialize_seq(type_path: &Tokens,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
is_struct: bool,
|
||||
@ -292,7 +360,7 @@ fn deserialize_seq(ident: &syn::Ident,
|
||||
}
|
||||
Some(path) => {
|
||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(
|
||||
ident, params, field.ty, path);
|
||||
params, field.ty, path);
|
||||
quote!({
|
||||
#wrapper
|
||||
_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);
|
||||
quote! {
|
||||
#type_path { #( #names: #vars ),* }
|
||||
@ -325,14 +393,20 @@ fn deserialize_seq(ident: &syn::Ident,
|
||||
}
|
||||
};
|
||||
|
||||
if params.has_getter {
|
||||
let this = ¶ms.this;
|
||||
result = quote! {
|
||||
_serde::export::Into::<#this>::into(#result)
|
||||
};
|
||||
}
|
||||
|
||||
quote_block! {
|
||||
#(#let_values)*
|
||||
_serde::export::Ok(#result)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct(ident: &syn::Ident,
|
||||
type_path: &Tokens,
|
||||
fn deserialize_newtype_struct(type_path: &Tokens,
|
||||
params: &Parameters,
|
||||
field: &Field)
|
||||
-> Tokens {
|
||||
@ -345,25 +419,33 @@ fn deserialize_newtype_struct(ident: &syn::Ident,
|
||||
}
|
||||
Some(path) => {
|
||||
let (wrapper, wrapper_ty) =
|
||||
wrap_deserialize_with(ident, params, field.ty, path);
|
||||
wrap_deserialize_with(params, field.ty, path);
|
||||
quote!({
|
||||
#wrapper
|
||||
try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let mut result = quote!(#type_path(#value));
|
||||
if params.has_getter {
|
||||
let this = ¶ms.this;
|
||||
result = quote! {
|
||||
_serde::export::Into::<#this>::into(#result)
|
||||
};
|
||||
}
|
||||
|
||||
quote! {
|
||||
#[inline]
|
||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||
where __E: _serde::Deserializer<'de>
|
||||
{
|
||||
_serde::export::Ok(#type_path(#value))
|
||||
_serde::export::Ok(#result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_struct(ident: &syn::Ident,
|
||||
variant_ident: Option<&syn::Ident>,
|
||||
fn deserialize_struct(variant_ident: Option<&syn::Ident>,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
item_attrs: &attr::Item,
|
||||
@ -372,28 +454,39 @@ fn deserialize_struct(ident: &syn::Ident,
|
||||
let is_enum = variant_ident.is_some();
|
||||
let is_untagged = deserializer.is_some();
|
||||
|
||||
let this = ¶ms.this;
|
||||
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 = ¶ms.local;
|
||||
quote!(#local)
|
||||
} else {
|
||||
quote!(#this)
|
||||
};
|
||||
|
||||
let type_path = match variant_ident {
|
||||
Some(variant_ident) => quote!(#ident::#variant_ident),
|
||||
None => quote!(#ident),
|
||||
Some(variant_ident) => quote!(#construct::#variant_ident),
|
||||
None => construct,
|
||||
};
|
||||
let expecting = match variant_ident {
|
||||
Some(variant_ident) => format!("struct variant {}::{}", ident, variant_ident),
|
||||
None => format!("struct {}", ident),
|
||||
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_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) =
|
||||
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 fields_stmt = Stmts(fields_stmt);
|
||||
let visit_map = Stmts(visit_map);
|
||||
|
||||
let visitor_expr = quote! {
|
||||
__Visitor {
|
||||
marker: _serde::export::PhantomData::<#ident #ty_generics>,
|
||||
marker: _serde::export::PhantomData::<#this #ty_generics>,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
}
|
||||
};
|
||||
@ -437,12 +530,12 @@ fn deserialize_struct(ident: &syn::Ident,
|
||||
#field_visitor
|
||||
|
||||
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 ()>,
|
||||
}
|
||||
|
||||
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 {
|
||||
_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,
|
||||
params: &Parameters,
|
||||
fn deserialize_item_enum(params: &Parameters,
|
||||
variants: &[Variant],
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
match *item_attrs.tag() {
|
||||
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 } => {
|
||||
deserialize_internally_tagged_enum(ident,
|
||||
params,
|
||||
deserialize_internally_tagged_enum(params,
|
||||
variants,
|
||||
item_attrs,
|
||||
tag)
|
||||
}
|
||||
attr::EnumTag::Adjacent { ref tag, ref content } => {
|
||||
deserialize_adjacently_tagged_enum(ident,
|
||||
params,
|
||||
deserialize_adjacently_tagged_enum(params,
|
||||
variants,
|
||||
item_attrs,
|
||||
tag,
|
||||
content)
|
||||
}
|
||||
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,
|
||||
params: &Parameters,
|
||||
fn deserialize_externally_tagged_enum(params: &Parameters,
|
||||
variants: &[Variant],
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
let this = ¶ms.this;
|
||||
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 expecting = format!("enum {}", ident);
|
||||
let expecting = format!("enum {}", params.type_name());
|
||||
|
||||
let variant_names_idents: Vec<_> = variants.iter()
|
||||
.enumerate()
|
||||
@ -527,8 +617,7 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
|
||||
.map(|(i, variant)| {
|
||||
let variant_name = field_i(i);
|
||||
|
||||
let block = Match(deserialize_externally_tagged_variant(ident,
|
||||
params,
|
||||
let block = Match(deserialize_externally_tagged_variant(params,
|
||||
variant,
|
||||
item_attrs));
|
||||
|
||||
@ -561,12 +650,12 @@ fn deserialize_externally_tagged_enum(ident: &syn::Ident,
|
||||
#variant_visitor
|
||||
|
||||
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 ()>,
|
||||
}
|
||||
|
||||
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 {
|
||||
_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,
|
||||
__Visitor {
|
||||
marker: _serde::export::PhantomData::<#ident #ty_generics>,
|
||||
marker: _serde::export::PhantomData::<#this #ty_generics>,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_internally_tagged_enum(ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
fn deserialize_internally_tagged_enum(params: &Parameters,
|
||||
variants: &[Variant],
|
||||
item_attrs: &attr::Item,
|
||||
tag: &str)
|
||||
@ -618,7 +706,6 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident,
|
||||
let variant_name = field_i(i);
|
||||
|
||||
let block = Match(deserialize_internally_tagged_variant(
|
||||
ident,
|
||||
params,
|
||||
variant,
|
||||
item_attrs,
|
||||
@ -645,13 +732,13 @@ fn deserialize_internally_tagged_enum(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
fn deserialize_adjacently_tagged_enum(params: &Parameters,
|
||||
variants: &[Variant],
|
||||
item_attrs: &attr::Item,
|
||||
tag: &str,
|
||||
content: &str)
|
||||
-> Fragment {
|
||||
let this = ¶ms.this;
|
||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
|
||||
|
||||
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 block = Match(deserialize_untagged_variant(
|
||||
ident,
|
||||
params,
|
||||
variant,
|
||||
item_attrs,
|
||||
@ -689,7 +775,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
|
||||
})
|
||||
.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 tag_or_content = quote! {
|
||||
@ -724,7 +810,7 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
|
||||
let variant_index = field_i(i);
|
||||
let variant_ident = &variant.ident;
|
||||
quote! {
|
||||
__Field::#variant_index => _serde::export::Ok(#ident::#variant_ident),
|
||||
__Field::#variant_index => _serde::export::Ok(#this::#variant_ident),
|
||||
}
|
||||
});
|
||||
missing_content = quote! {
|
||||
@ -755,12 +841,12 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
|
||||
|
||||
struct __Seed #de_impl_generics #where_clause {
|
||||
field: __Field,
|
||||
marker: _serde::export::PhantomData<#ident #ty_generics>,
|
||||
marker: _serde::export::PhantomData<#this #ty_generics>,
|
||||
lifetime: _serde::export::PhantomData<&'de ()>,
|
||||
}
|
||||
|
||||
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>
|
||||
where __D: _serde::Deserializer<'de>
|
||||
@ -772,12 +858,12 @@ fn deserialize_adjacently_tagged_enum(ident: &syn::Ident,
|
||||
}
|
||||
|
||||
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 ()>,
|
||||
}
|
||||
|
||||
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 {
|
||||
_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];
|
||||
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS,
|
||||
__Visitor {
|
||||
marker: _serde::export::PhantomData::<#ident #ty_generics>,
|
||||
marker: _serde::export::PhantomData::<#this #ty_generics>,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_untagged_enum(ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
fn deserialize_untagged_enum(params: &Parameters,
|
||||
variants: &[Variant],
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
@ -893,7 +978,6 @@ fn deserialize_untagged_enum(ident: &syn::Ident,
|
||||
.filter(|variant| !variant.attrs.skip_deserializing())
|
||||
.map(|variant| {
|
||||
Expr(deserialize_untagged_variant(
|
||||
ident,
|
||||
params,
|
||||
variant,
|
||||
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
|
||||
// better to save all the errors and combine them into one message that
|
||||
// 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! {
|
||||
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,
|
||||
params: &Parameters,
|
||||
fn deserialize_externally_tagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
@ -931,28 +1014,26 @@ fn deserialize_externally_tagged_variant(ident: &syn::Ident,
|
||||
|
||||
match variant.style {
|
||||
Style::Unit => {
|
||||
let this = ¶ms.this;
|
||||
quote_block! {
|
||||
try!(_serde::de::VariantVisitor::visit_unit(__visitor));
|
||||
_serde::export::Ok(#ident::#variant_ident)
|
||||
_serde::export::Ok(#this::#variant_ident)
|
||||
}
|
||||
}
|
||||
Style::Newtype => {
|
||||
deserialize_externally_tagged_newtype_variant(ident,
|
||||
variant_ident,
|
||||
deserialize_externally_tagged_newtype_variant(variant_ident,
|
||||
params,
|
||||
&variant.fields[0])
|
||||
}
|
||||
Style::Tuple => {
|
||||
deserialize_tuple(ident,
|
||||
Some(variant_ident),
|
||||
deserialize_tuple(Some(variant_ident),
|
||||
params,
|
||||
&variant.fields,
|
||||
item_attrs,
|
||||
None)
|
||||
}
|
||||
Style::Struct => {
|
||||
deserialize_struct(ident,
|
||||
Some(variant_ident),
|
||||
deserialize_struct(Some(variant_ident),
|
||||
params,
|
||||
&variant.fields,
|
||||
item_attrs,
|
||||
@ -961,8 +1042,7 @@ fn deserialize_externally_tagged_variant(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
fn deserialize_internally_tagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
item_attrs: &attr::Item,
|
||||
deserializer: Tokens)
|
||||
@ -971,16 +1051,16 @@ fn deserialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
|
||||
match variant.style {
|
||||
Style::Unit => {
|
||||
let type_name = ident.as_ref();
|
||||
let this = ¶ms.this;
|
||||
let type_name = params.type_name();
|
||||
let variant_name = variant.ident.as_ref();
|
||||
quote_block! {
|
||||
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 => {
|
||||
deserialize_untagged_variant(ident,
|
||||
params,
|
||||
deserialize_untagged_variant(params,
|
||||
variant,
|
||||
item_attrs,
|
||||
deserializer)
|
||||
@ -989,8 +1069,7 @@ fn deserialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_untagged_variant(ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
fn deserialize_untagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
item_attrs: &attr::Item,
|
||||
deserializer: Tokens)
|
||||
@ -999,7 +1078,8 @@ fn deserialize_untagged_variant(ident: &syn::Ident,
|
||||
|
||||
match variant.style {
|
||||
Style::Unit => {
|
||||
let type_name = ident.as_ref();
|
||||
let this = ¶ms.this;
|
||||
let type_name = params.type_name();
|
||||
let variant_name = variant.ident.as_ref();
|
||||
quote_expr! {
|
||||
_serde::export::Result::map(
|
||||
@ -1007,27 +1087,24 @@ fn deserialize_untagged_variant(ident: &syn::Ident,
|
||||
#deserializer,
|
||||
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
|
||||
),
|
||||
|()| #ident::#variant_ident)
|
||||
|()| #this::#variant_ident)
|
||||
}
|
||||
}
|
||||
Style::Newtype => {
|
||||
deserialize_untagged_newtype_variant(ident,
|
||||
variant_ident,
|
||||
deserialize_untagged_newtype_variant(variant_ident,
|
||||
params,
|
||||
&variant.fields[0],
|
||||
deserializer)
|
||||
}
|
||||
Style::Tuple => {
|
||||
deserialize_tuple(ident,
|
||||
Some(variant_ident),
|
||||
deserialize_tuple(Some(variant_ident),
|
||||
params,
|
||||
&variant.fields,
|
||||
item_attrs,
|
||||
Some(deserializer))
|
||||
}
|
||||
Style::Struct => {
|
||||
deserialize_struct(ident,
|
||||
Some(variant_ident),
|
||||
deserialize_struct(Some(variant_ident),
|
||||
params,
|
||||
&variant.fields,
|
||||
item_attrs,
|
||||
@ -1036,56 +1113,56 @@ fn deserialize_untagged_variant(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_externally_tagged_newtype_variant(ident: &syn::Ident,
|
||||
variant_ident: &syn::Ident,
|
||||
fn deserialize_externally_tagged_newtype_variant(variant_ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
field: &Field)
|
||||
-> Fragment {
|
||||
let this = ¶ms.this;
|
||||
match field.attrs.deserialize_with() {
|
||||
None => {
|
||||
let field_ty = &field.ty;
|
||||
quote_expr! {
|
||||
_serde::export::Result::map(
|
||||
_serde::de::VariantVisitor::visit_newtype::<#field_ty>(__visitor),
|
||||
#ident::#variant_ident)
|
||||
#this::#variant_ident)
|
||||
}
|
||||
}
|
||||
Some(path) => {
|
||||
let (wrapper, wrapper_ty) =
|
||||
wrap_deserialize_with(ident, params, field.ty, path);
|
||||
wrap_deserialize_with(params, field.ty, path);
|
||||
quote_block! {
|
||||
#wrapper
|
||||
_serde::export::Result::map(
|
||||
_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,
|
||||
variant_ident: &syn::Ident,
|
||||
fn deserialize_untagged_newtype_variant(variant_ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
field: &Field,
|
||||
deserializer: Tokens)
|
||||
-> Fragment {
|
||||
let this = ¶ms.this;
|
||||
match field.attrs.deserialize_with() {
|
||||
None => {
|
||||
let field_ty = &field.ty;
|
||||
quote_expr! {
|
||||
_serde::export::Result::map(
|
||||
<#field_ty as _serde::Deserialize>::deserialize(#deserializer),
|
||||
#ident::#variant_ident)
|
||||
#this::#variant_ident)
|
||||
}
|
||||
}
|
||||
Some(path) => {
|
||||
let (wrapper, wrapper_ty) =
|
||||
wrap_deserialize_with(ident, params, field.ty, path);
|
||||
wrap_deserialize_with(params, field.ty, path);
|
||||
quote_block! {
|
||||
#wrapper
|
||||
_serde::export::Result::map(
|
||||
<#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,
|
||||
struct_path: Tokens,
|
||||
fn deserialize_struct_visitor(struct_path: Tokens,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
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 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)
|
||||
}
|
||||
|
||||
fn deserialize_map(ident: &syn::Ident,
|
||||
struct_path: Tokens,
|
||||
fn deserialize_map(struct_path: Tokens,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
item_attrs: &attr::Item)
|
||||
@ -1266,7 +1341,7 @@ fn deserialize_map(ident: &syn::Ident,
|
||||
}
|
||||
Some(path) => {
|
||||
let (wrapper, wrapper_ty) = wrap_deserialize_with(
|
||||
ident, params, field.ty, path);
|
||||
params, field.ty, path);
|
||||
quote!({
|
||||
#wrapper
|
||||
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 = ¶ms.this;
|
||||
result = quote! {
|
||||
_serde::export::Into::<#this>::into(#result)
|
||||
};
|
||||
}
|
||||
|
||||
quote_block! {
|
||||
#(#let_values)*
|
||||
|
||||
@ -1363,7 +1446,7 @@ fn deserialize_map(ident: &syn::Ident,
|
||||
|
||||
#(#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 = "...")]`
|
||||
/// in a trait to prevent it from accessing the internal `Deserialize` state.
|
||||
fn wrap_deserialize_with(ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
fn wrap_deserialize_with(params: &Parameters,
|
||||
field_ty: &syn::Ty,
|
||||
deserialize_with: &syn::Path)
|
||||
-> (Tokens, Tokens) {
|
||||
let this = ¶ms.this;
|
||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params);
|
||||
|
||||
let wrapper = quote! {
|
||||
struct __DeserializeWith #de_impl_generics #where_clause {
|
||||
value: #field_ty,
|
||||
phantom: _serde::export::PhantomData<#ident #ty_generics>,
|
||||
phantom: _serde::export::PhantomData<#this #ty_generics>,
|
||||
lifetime: _serde::export::PhantomData<&'de ()>,
|
||||
}
|
||||
|
||||
@ -1444,11 +1527,7 @@ struct DeImplGenerics<'a>(&'a Parameters);
|
||||
impl<'a> ToTokens for DeImplGenerics<'a> {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
let mut generics = self.0.generics.clone();
|
||||
generics.lifetimes.insert(0, syn::LifetimeDef {
|
||||
attrs: Vec::new(),
|
||||
lifetime: syn::Lifetime::new("'de"),
|
||||
bounds: self.0.borrowed.iter().cloned().collect(),
|
||||
});
|
||||
generics.lifetimes.insert(0, self.0.de_lifetime_def());
|
||||
let (impl_generics, _, _) = generics.split_for_impl();
|
||||
impl_generics.to_tokens(tokens);
|
||||
}
|
||||
|
@ -6,21 +6,31 @@ use fragment::{Fragment, Stmts, Match};
|
||||
use internals::ast::{Body, Field, Item, Style, Variant};
|
||||
use internals::{self, attr};
|
||||
|
||||
use std::u32;
|
||||
|
||||
pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String> {
|
||||
let ctxt = internals::Ctxt::new();
|
||||
let item = Item::from_ast(&ctxt, item);
|
||||
try!(ctxt.check());
|
||||
|
||||
let ident = &item.ident;
|
||||
let generics = build_generics(&item);
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
let params = Parameters::new(&item);
|
||||
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
|
||||
let body = Stmts(serialize_body(&item, &generics));
|
||||
let body = Stmts(serialize_body(&item, ¶ms));
|
||||
|
||||
Ok(quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const #dummy_const: () = {
|
||||
extern crate serde as _serde;
|
||||
let impl_item = if let Some(remote) = item.attrs.remote() {
|
||||
quote! {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
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]
|
||||
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
// field type that will be serialized by us.
|
||||
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()
|
||||
}
|
||||
|
||||
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() {
|
||||
serialize_into(into_type)
|
||||
serialize_into(params, into_type)
|
||||
} else {
|
||||
match item.body {
|
||||
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) => {
|
||||
if fields.iter().any(|field| field.ident.is_none()) {
|
||||
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) => {
|
||||
if fields.iter().any(|field| field.ident.is_some()) {
|
||||
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) => {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_into(into_type: &syn::Ty) -> Fragment {
|
||||
fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment {
|
||||
let self_var = ¶ms.self_var;
|
||||
quote_block! {
|
||||
_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)
|
||||
}
|
||||
}
|
||||
@ -104,16 +171,15 @@ fn serialize_unit_struct(item_attrs: &attr::Item) -> Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_newtype_struct(params: &Parameters,
|
||||
field: &Field,
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
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() {
|
||||
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! {
|
||||
@ -121,15 +187,13 @@ fn serialize_newtype_struct(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_tuple_struct(params: &Parameters,
|
||||
fields: &[Field],
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
let serialize_stmts =
|
||||
serialize_tuple_struct_visitor(ident,
|
||||
fields,
|
||||
generics,
|
||||
serialize_tuple_struct_visitor(fields,
|
||||
params,
|
||||
false,
|
||||
quote!(_serde::ser::SerializeTupleStruct::serialize_field));
|
||||
|
||||
@ -144,15 +208,15 @@ fn serialize_tuple_struct(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_struct(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_struct(params: &Parameters,
|
||||
fields: &[Field],
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
assert!(fields.len() as u64 <= u32::MAX as u64);
|
||||
|
||||
let serialize_fields =
|
||||
serialize_struct_visitor(ident,
|
||||
fields,
|
||||
generics,
|
||||
serialize_struct_visitor(fields,
|
||||
params,
|
||||
false,
|
||||
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 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() {
|
||||
Some(path) => quote!(if #path(#field_expr) { 0 } else { 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));
|
||||
@ -182,40 +247,42 @@ fn serialize_struct(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_item_enum(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_item_enum(params: &Parameters,
|
||||
variants: &[Variant],
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
assert!(variants.len() as u64 <= u32::MAX as u64);
|
||||
|
||||
let self_var = ¶ms.self_var;
|
||||
|
||||
let arms: Vec<_> = variants.iter()
|
||||
.enumerate()
|
||||
.map(|(variant_index, variant)| {
|
||||
serialize_variant(ident,
|
||||
generics,
|
||||
serialize_variant(params,
|
||||
variant,
|
||||
variant_index,
|
||||
variant_index as u32,
|
||||
item_attrs)
|
||||
})
|
||||
.collect();
|
||||
|
||||
quote_expr! {
|
||||
match *self {
|
||||
match *#self_var {
|
||||
#(#arms)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_variant(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
item_attrs: &attr::Item)
|
||||
-> Tokens {
|
||||
let this = ¶ms.this;
|
||||
let variant_ident = variant.ident.clone();
|
||||
|
||||
if variant.attrs.skip_serializing() {
|
||||
let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
|
||||
ident, variant_ident);
|
||||
params.type_name(), variant_ident);
|
||||
let skipped_err = quote! {
|
||||
_serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
|
||||
};
|
||||
@ -225,26 +292,26 @@ fn serialize_variant(ident: &syn::Ident,
|
||||
Style::Struct => quote!( {..} ),
|
||||
};
|
||||
quote! {
|
||||
#ident::#variant_ident #fields_pat => #skipped_err,
|
||||
#this::#variant_ident #fields_pat => #skipped_err,
|
||||
}
|
||||
} else {
|
||||
// variant wasn't skipped
|
||||
let case = match variant.style {
|
||||
Style::Unit => {
|
||||
quote! {
|
||||
#ident::#variant_ident
|
||||
#this::#variant_ident
|
||||
}
|
||||
}
|
||||
Style::Newtype => {
|
||||
quote! {
|
||||
#ident::#variant_ident(ref __field0)
|
||||
#this::#variant_ident(ref __field0)
|
||||
}
|
||||
}
|
||||
Style::Tuple => {
|
||||
let field_names = (0..variant.fields.len())
|
||||
.map(|i| Ident::new(format!("__field{}", i)));
|
||||
quote! {
|
||||
#ident::#variant_ident(#(ref #field_names),*)
|
||||
#this::#variant_ident(#(ref #field_names),*)
|
||||
}
|
||||
}
|
||||
Style::Struct => {
|
||||
@ -252,35 +319,32 @@ fn serialize_variant(ident: &syn::Ident,
|
||||
.iter()
|
||||
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
|
||||
quote! {
|
||||
#ident::#variant_ident { #(ref #fields),* }
|
||||
#this::#variant_ident { #(ref #fields),* }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let body = Match(match *item_attrs.tag() {
|
||||
attr::EnumTag::External => {
|
||||
serialize_externally_tagged_variant(ident,
|
||||
generics,
|
||||
serialize_externally_tagged_variant(params,
|
||||
variant,
|
||||
variant_index,
|
||||
item_attrs)
|
||||
}
|
||||
attr::EnumTag::Internal { ref tag } => {
|
||||
serialize_internally_tagged_variant(ident,
|
||||
generics,
|
||||
serialize_internally_tagged_variant(params,
|
||||
variant,
|
||||
item_attrs,
|
||||
tag)
|
||||
}
|
||||
attr::EnumTag::Adjacent { ref tag, ref content } => {
|
||||
serialize_adjacently_tagged_variant(ident,
|
||||
generics,
|
||||
serialize_adjacently_tagged_variant(params,
|
||||
variant,
|
||||
item_attrs,
|
||||
tag,
|
||||
content)
|
||||
}
|
||||
attr::EnumTag::None => serialize_untagged_variant(ident, generics, variant, item_attrs),
|
||||
attr::EnumTag::None => serialize_untagged_variant(params, variant, item_attrs),
|
||||
});
|
||||
|
||||
quote! {
|
||||
@ -289,10 +353,9 @@ fn serialize_variant(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_externally_tagged_variant(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_externally_tagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
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 mut field_expr = quote!(__field0);
|
||||
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! {
|
||||
@ -332,8 +395,7 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
|
||||
variant_index: variant_index,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
ident,
|
||||
generics,
|
||||
params,
|
||||
&variant.fields)
|
||||
}
|
||||
Style::Struct => {
|
||||
@ -341,16 +403,14 @@ fn serialize_externally_tagged_variant(ident: &syn::Ident,
|
||||
variant_index: variant_index,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
ident,
|
||||
generics,
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_internally_tagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
item_attrs: &attr::Item,
|
||||
tag: &str)
|
||||
@ -358,7 +418,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
let type_name = item_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();
|
||||
|
||||
match variant.style {
|
||||
@ -375,7 +435,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
let field = &variant.fields[0];
|
||||
let mut field_expr = quote!(__field0);
|
||||
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! {
|
||||
@ -394,8 +454,7 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
tag: tag,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
ident,
|
||||
generics,
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name)
|
||||
}
|
||||
@ -403,13 +462,13 @@ fn serialize_internally_tagged_variant(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_adjacently_tagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
item_attrs: &attr::Item,
|
||||
tag: &str,
|
||||
content: &str)
|
||||
-> Fragment {
|
||||
let this = ¶ms.this;
|
||||
let type_name = item_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 mut field_expr = quote!(__field0);
|
||||
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! {
|
||||
@ -436,14 +495,12 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
|
||||
}
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(TupleVariant::Untagged,
|
||||
ident,
|
||||
generics,
|
||||
params,
|
||||
&variant.fields)
|
||||
}
|
||||
Style::Struct => {
|
||||
serialize_struct_variant(StructVariant::Untagged,
|
||||
ident,
|
||||
generics,
|
||||
params,
|
||||
&variant.fields,
|
||||
&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(¶ms.generics, "'__a");
|
||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||
|
||||
quote_block! {
|
||||
struct __AdjacentlyTagged #wrapper_generics #where_clause {
|
||||
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 {
|
||||
@ -493,14 +550,13 @@ fn serialize_adjacently_tagged_variant(ident: &syn::Ident,
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #content, &__AdjacentlyTagged {
|
||||
data: (#(#fields_ident,)*),
|
||||
phantom: _serde::export::PhantomData::<#ident #ty_generics>,
|
||||
phantom: _serde::export::PhantomData::<#this #ty_generics>,
|
||||
}));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_untagged_variant(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn serialize_untagged_variant(params: &Parameters,
|
||||
variant: &Variant,
|
||||
item_attrs: &attr::Item)
|
||||
-> Fragment {
|
||||
@ -514,7 +570,7 @@ fn serialize_untagged_variant(ident: &syn::Ident,
|
||||
let field = &variant.fields[0];
|
||||
let mut field_expr = quote!(__field0);
|
||||
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! {
|
||||
@ -522,13 +578,12 @@ fn serialize_untagged_variant(ident: &syn::Ident,
|
||||
}
|
||||
}
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(TupleVariant::Untagged, ident, generics, &variant.fields)
|
||||
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
||||
}
|
||||
Style::Struct => {
|
||||
let type_name = item_attrs.name().serialize_name();
|
||||
serialize_struct_variant(StructVariant::Untagged,
|
||||
ident,
|
||||
generics,
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name)
|
||||
}
|
||||
@ -538,15 +593,14 @@ fn serialize_untagged_variant(ident: &syn::Ident,
|
||||
enum TupleVariant {
|
||||
ExternallyTagged {
|
||||
type_name: String,
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
variant_name: String,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(context: TupleVariant,
|
||||
ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
params: &Parameters,
|
||||
fields: &[Field])
|
||||
-> Fragment {
|
||||
let method = match context {
|
||||
@ -557,7 +611,7 @@ fn serialize_tuple_variant(context: TupleVariant,
|
||||
};
|
||||
|
||||
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 let_mut = mut_if(len > 0);
|
||||
@ -589,7 +643,7 @@ fn serialize_tuple_variant(context: TupleVariant,
|
||||
|
||||
enum StructVariant<'a> {
|
||||
ExternallyTagged {
|
||||
variant_index: usize,
|
||||
variant_index: u32,
|
||||
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>,
|
||||
ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str)
|
||||
-> Fragment {
|
||||
@ -610,7 +663,7 @@ fn serialize_struct_variant<'a>(context: StructVariant<'a>,
|
||||
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()
|
||||
.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,
|
||||
fields: &[Field],
|
||||
generics: &syn::Generics,
|
||||
fn serialize_tuple_struct_visitor(fields: &[Field],
|
||||
params: &Parameters,
|
||||
is_enum: bool,
|
||||
func: Tokens)
|
||||
-> Vec<Tokens> {
|
||||
@ -685,8 +737,7 @@ fn serialize_tuple_struct_visitor(ident: &syn::Ident,
|
||||
let id = Ident::new(format!("__field{}", i));
|
||||
quote!(#id)
|
||||
} else {
|
||||
let i = Ident::new(i);
|
||||
quote!(&self.#i)
|
||||
get_field(params, field, i)
|
||||
};
|
||||
|
||||
let skip = field.attrs
|
||||
@ -695,7 +746,7 @@ fn serialize_tuple_struct_visitor(ident: &syn::Ident,
|
||||
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr =
|
||||
wrap_serialize_with(ident, generics, field.ty, path, field_expr);
|
||||
wrap_serialize_with(params, field.ty, path, field_expr);
|
||||
}
|
||||
|
||||
let ser = quote! {
|
||||
@ -710,9 +761,8 @@ fn serialize_tuple_struct_visitor(ident: &syn::Ident,
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn serialize_struct_visitor(ident: &syn::Ident,
|
||||
fields: &[Field],
|
||||
generics: &syn::Generics,
|
||||
fn serialize_struct_visitor(fields: &[Field],
|
||||
params: &Parameters,
|
||||
is_enum: bool,
|
||||
func: Tokens)
|
||||
-> Vec<Tokens> {
|
||||
@ -723,7 +773,7 @@ fn serialize_struct_visitor(ident: &syn::Ident,
|
||||
let mut field_expr = if is_enum {
|
||||
quote!(#field_ident)
|
||||
} else {
|
||||
quote!(&self.#field_ident)
|
||||
get_field(params, field, field_ident)
|
||||
};
|
||||
|
||||
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() {
|
||||
field_expr =
|
||||
wrap_serialize_with(ident, generics, field.ty, path, field_expr)
|
||||
wrap_serialize_with(params, field.ty, path, field_expr)
|
||||
}
|
||||
|
||||
let ser = quote! {
|
||||
@ -749,21 +799,21 @@ fn serialize_struct_visitor(ident: &syn::Ident,
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn wrap_serialize_with(ident: &syn::Ident,
|
||||
generics: &syn::Generics,
|
||||
fn wrap_serialize_with(params: &Parameters,
|
||||
field_ty: &syn::Ty,
|
||||
serialize_with: &syn::Path,
|
||||
value: Tokens)
|
||||
-> Tokens {
|
||||
let (_, ty_generics, where_clause) = generics.split_for_impl();
|
||||
let this = ¶ms.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(¶ms.generics, "'__a");
|
||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||
|
||||
quote!({
|
||||
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
||||
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 {
|
||||
@ -776,7 +826,7 @@ fn wrap_serialize_with(ident: &syn::Ident,
|
||||
|
||||
&__SerializeWith {
|
||||
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> {
|
||||
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 = ¶ms.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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
|
||||
forward_to_deserialize! {
|
||||
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>
|
||||
@ -645,6 +645,6 @@ impl<'de> de::Deserializer<'de> for BytesDeserializer {
|
||||
forward_to_deserialize! {
|
||||
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
|
||||
struct struct_field tuple enum ignored_any byte_buf
|
||||
struct identifier tuple enum ignored_any byte_buf
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
name: &'static str,
|
||||
_variant_index: usize,
|
||||
_variant_index: u32,
|
||||
variant: &'static str)
|
||||
-> Result<(), Error> {
|
||||
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,
|
||||
name: &'static str,
|
||||
_variant_index: usize,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), Error>
|
||||
@ -217,7 +217,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
name: &'static str,
|
||||
_variant_index: usize,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self, Error> {
|
||||
@ -237,7 +237,7 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
name: &'static str,
|
||||
_variant_index: usize,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize)
|
||||
-> Result<Self, Error> {
|
||||
|
17
test_suite/tests/compile-fail/remote/bad_getter.rs
Normal file
17
test_suite/tests/compile-fail/remote/bad_getter.rs
Normal file
@ -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() {}
|
16
test_suite/tests/compile-fail/remote/bad_remote.rs
Normal file
16
test_suite/tests/compile-fail/remote/bad_remote.rs
Normal file
@ -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() {}
|
19
test_suite/tests/compile-fail/remote/enum_getter.rs
Normal file
19
test_suite/tests/compile-fail/remote/enum_getter.rs
Normal file
@ -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() {}
|
17
test_suite/tests/compile-fail/remote/missing_field.rs
Normal file
17
test_suite/tests/compile-fail/remote/missing_field.rs
Normal file
@ -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() {}
|
16
test_suite/tests/compile-fail/remote/nonremote_getter.rs
Normal file
16
test_suite/tests/compile-fail/remote/nonremote_getter.rs
Normal file
@ -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() {}
|
16
test_suite/tests/compile-fail/remote/unknown_field.rs
Normal file
16
test_suite/tests/compile-fail/remote/unknown_field.rs
Normal file
@ -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() {}
|
12
test_suite/tests/compile-fail/remote/wrong_de.rs
Normal file
12
test_suite/tests/compile-fail/remote/wrong_de.rs
Normal file
@ -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() {}
|
23
test_suite/tests/compile-fail/remote/wrong_getter.rs
Normal file
23
test_suite/tests/compile-fail/remote/wrong_getter.rs
Normal file
@ -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() {}
|
16
test_suite/tests/compile-fail/remote/wrong_ser.rs
Normal file
16
test_suite/tests/compile-fail/remote/wrong_ser.rs
Normal file
@ -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() {}
|
@ -242,14 +242,6 @@ declare_tests! {
|
||||
UnitStruct => &[
|
||||
Token::UnitStruct("UnitStruct"),
|
||||
],
|
||||
UnitStruct => &[
|
||||
Token::Seq(Some(0)),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
UnitStruct => &[
|
||||
Token::Seq(None),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_newtype_struct {
|
||||
NewtypeStruct(1) => &[
|
||||
@ -1036,4 +1028,11 @@ declare_error_tests! {
|
||||
],
|
||||
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
test_suite/tests/test_remote.rs
Normal file
184
test_suite/tests/test_remote.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -4,10 +4,12 @@ extern crate serde_derive;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
use std::time::Duration;
|
||||
use std::ffi::CString;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::str;
|
||||
|
||||
extern crate serde;
|
||||
|
||||
extern crate serde_test;
|
||||
|
Loading…
x
Reference in New Issue
Block a user