From 74e15ea9f5ac0c9e75560a085a78001d2cf51232 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 6 Apr 2017 15:24:16 -0700 Subject: [PATCH 1/2] Configurable forward_to_deserialize --- serde/src/macros.rs | 153 ++++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 64 deletions(-) diff --git a/serde/src/macros.rs b/serde/src/macros.rs index 5873e1a7..b453e7c1 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -1,11 +1,14 @@ #[doc(hidden)] #[macro_export] macro_rules! forward_to_deserialize_method { - ($func:ident($($arg:ty),*)) => { + ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => { #[inline] - fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> $crate::export::Result<__V::Value, Self::Error> - where __V: $crate::de::Visitor<'de> + fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error> + where $v: $crate::de::Visitor<$l> { + $( + let _ = $arg; + )* self.deserialize(visitor) } }; @@ -14,92 +17,92 @@ macro_rules! forward_to_deserialize_method { #[doc(hidden)] #[macro_export] macro_rules! forward_to_deserialize_helper { - (bool) => { - forward_to_deserialize_method!{deserialize_bool()} + (bool<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_bool<$l, $v>()} }; - (u8) => { - forward_to_deserialize_method!{deserialize_u8()} + (u8<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_u8<$l, $v>()} }; - (u16) => { - forward_to_deserialize_method!{deserialize_u16()} + (u16<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_u16<$l, $v>()} }; - (u32) => { - forward_to_deserialize_method!{deserialize_u32()} + (u32<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_u32<$l, $v>()} }; - (u64) => { - forward_to_deserialize_method!{deserialize_u64()} + (u64<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_u64<$l, $v>()} }; - (i8) => { - forward_to_deserialize_method!{deserialize_i8()} + (i8<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_i8<$l, $v>()} }; - (i16) => { - forward_to_deserialize_method!{deserialize_i16()} + (i16<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_i16<$l, $v>()} }; - (i32) => { - forward_to_deserialize_method!{deserialize_i32()} + (i32<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_i32<$l, $v>()} }; - (i64) => { - forward_to_deserialize_method!{deserialize_i64()} + (i64<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_i64<$l, $v>()} }; - (f32) => { - forward_to_deserialize_method!{deserialize_f32()} + (f32<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_f32<$l, $v>()} }; - (f64) => { - forward_to_deserialize_method!{deserialize_f64()} + (f64<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_f64<$l, $v>()} }; - (char) => { - forward_to_deserialize_method!{deserialize_char()} + (char<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_char<$l, $v>()} }; - (str) => { - forward_to_deserialize_method!{deserialize_str()} + (str<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_str<$l, $v>()} }; - (string) => { - forward_to_deserialize_method!{deserialize_string()} + (string<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_string<$l, $v>()} }; - (unit) => { - forward_to_deserialize_method!{deserialize_unit()} + (unit<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_unit<$l, $v>()} }; - (option) => { - forward_to_deserialize_method!{deserialize_option()} + (option<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_option<$l, $v>()} }; - (seq) => { - forward_to_deserialize_method!{deserialize_seq()} + (seq<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_seq<$l, $v>()} }; - (seq_fixed_size) => { - forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)} + (seq_fixed_size<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_seq_fixed_size<$l, $v>(len: usize)} }; - (bytes) => { - forward_to_deserialize_method!{deserialize_bytes()} + (bytes<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_bytes<$l, $v>()} }; - (byte_buf) => { - forward_to_deserialize_method!{deserialize_byte_buf()} + (byte_buf<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_byte_buf<$l, $v>()} }; - (map) => { - forward_to_deserialize_method!{deserialize_map()} + (map<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_map<$l, $v>()} }; - (unit_struct) => { - forward_to_deserialize_method!{deserialize_unit_struct(&'static str)} + (unit_struct<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_unit_struct<$l, $v>(name: &'static str)} }; - (newtype_struct) => { - forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)} + (newtype_struct<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)} }; - (tuple_struct) => { - forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)} + (tuple_struct<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)} }; - (struct) => { - forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])} + (struct<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])} }; - (struct_field) => { - forward_to_deserialize_method!{deserialize_struct_field()} + (struct_field<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_struct_field<$l, $v>()} }; - (tuple) => { - forward_to_deserialize_method!{deserialize_tuple(usize)} + (tuple<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_tuple<$l, $v>(len: usize)} }; - (enum) => { - forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])} + (enum<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])} }; - (ignored_any) => { - forward_to_deserialize_method!{deserialize_ignored_any()} + (ignored_any<$l:tt, $v:ident>) => { + forward_to_deserialize_method!{deserialize_ignored_any<$l, $v>()} }; } @@ -184,11 +187,33 @@ macro_rules! forward_to_deserialize_helper { /// ``` /// /// The macro assumes the convention that your `Deserializer` lifetime parameter -/// is called `'de`. It will not work if the `Deserializer` lifetime parameter -/// is called something different. +/// is called `'de` and that the `Visitor` type parameters on each method are +/// called `V`. A different type parameter and a different lifetime can be +/// specified explicitly if necessary. +/// +/// ```rust +/// # #[macro_use] extern crate serde; +/// # use serde::de::{value, Deserializer, Visitor}; +/// # pub struct MyDeserializer; +/// # impl<'q> Deserializer<'q> for MyDeserializer { +/// # type Error = value::Error; +/// # fn deserialize(self, visitor: V) -> Result +/// # where V: Visitor<'q> { unimplemented!() } +/// 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 +/// } +/// # } +/// # fn main() {} +/// ``` #[macro_export] macro_rules! forward_to_deserialize { + (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { + $(forward_to_deserialize_helper!{$func<$lifetime, $visitor>})* + }; ($($func:ident)*) => { - $(forward_to_deserialize_helper!{$func})* + $(forward_to_deserialize_helper!{$func<'de, V>})* }; } From 9271f7c48cf11863a24a2a45632e9a825d091e16 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 8 Apr 2017 22:46:53 -0700 Subject: [PATCH 2/2] Use a deserializer in which V would conflict --- serde/src/macros.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/serde/src/macros.rs b/serde/src/macros.rs index b453e7c1..12c488a9 100644 --- a/serde/src/macros.rs +++ b/serde/src/macros.rs @@ -192,13 +192,24 @@ macro_rules! forward_to_deserialize_helper { /// specified explicitly if necessary. /// /// ```rust -/// # #[macro_use] extern crate serde; +/// # #[macro_use] +/// # extern crate serde; +/// # +/// # use std::marker::PhantomData; +/// # /// # use serde::de::{value, Deserializer, Visitor}; -/// # pub struct MyDeserializer; -/// # impl<'q> Deserializer<'q> for MyDeserializer { -/// # type Error = value::Error; -/// # fn deserialize(self, visitor: V) -> Result -/// # where V: Visitor<'q> { unimplemented!() } +/// # +/// # struct MyDeserializer(PhantomData); +/// # +/// # impl<'q, V> Deserializer<'q> for MyDeserializer { +/// # type Error = value::Error; +/// # +/// # fn deserialize(self, visitor: W) -> Result +/// # where W: Visitor<'q> +/// # { +/// # unimplemented!() +/// # } +/// # /// forward_to_deserialize! { /// > /// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option @@ -206,6 +217,7 @@ macro_rules! forward_to_deserialize_helper { /// tuple_struct struct struct_field tuple enum ignored_any /// } /// # } +/// # /// # fn main() {} /// ``` #[macro_export]