236 lines
8.2 KiB
Rust
236 lines
8.2 KiB
Rust
// Super explicit first paragraph because this shows up at the top level and
|
|
// trips up people who are just looking for basic Serialize / Deserialize
|
|
// documentation.
|
|
//
|
|
/// Helper macro when implementing the `Deserializer` part of a new data format
|
|
/// for Serde.
|
|
///
|
|
/// Some [`Deserializer`] implementations for self-describing formats do not
|
|
/// care what hint the [`Visitor`] gives them, they just want to blindly call
|
|
/// the [`Visitor`] method corresponding to the data they can tell is in the
|
|
/// input. This requires repetitive implementations of all the [`Deserializer`]
|
|
/// trait methods.
|
|
///
|
|
/// ```edition2018
|
|
/// # use serde::forward_to_deserialize_any;
|
|
/// # use serde::de::{value, Deserializer, Visitor};
|
|
/// #
|
|
/// # struct MyDeserializer;
|
|
/// #
|
|
/// # impl<'de> Deserializer<'de> for MyDeserializer {
|
|
/// # type Error = value::Error;
|
|
/// #
|
|
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
|
|
/// # where
|
|
/// # V: Visitor<'de>,
|
|
/// # {
|
|
/// # unimplemented!()
|
|
/// # }
|
|
/// #
|
|
/// #[inline]
|
|
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
|
/// where
|
|
/// V: Visitor<'de>,
|
|
/// {
|
|
/// self.deserialize_any(visitor)
|
|
/// }
|
|
/// #
|
|
/// # forward_to_deserialize_any! {
|
|
/// # i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
/// # bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
/// # tuple_struct map struct enum identifier ignored_any
|
|
/// # }
|
|
/// # }
|
|
/// ```
|
|
///
|
|
/// The `forward_to_deserialize_any!` macro implements these simple forwarding
|
|
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
|
|
/// You can choose which methods to forward.
|
|
///
|
|
/// ```edition2018
|
|
/// # use serde::forward_to_deserialize_any;
|
|
/// # use serde::de::{value, Deserializer, Visitor};
|
|
/// #
|
|
/// # struct MyDeserializer;
|
|
/// #
|
|
/// impl<'de> Deserializer<'de> for MyDeserializer {
|
|
/// # type Error = value::Error;
|
|
/// #
|
|
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
|
/// where
|
|
/// V: Visitor<'de>,
|
|
/// {
|
|
/// /* ... */
|
|
/// # let _ = visitor;
|
|
/// # unimplemented!()
|
|
/// }
|
|
///
|
|
/// forward_to_deserialize_any! {
|
|
/// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
/// bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
/// tuple_struct map struct enum identifier ignored_any
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// The macro assumes the convention that your `Deserializer` lifetime parameter
|
|
/// 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.
|
|
///
|
|
/// ```edition2018
|
|
/// # use std::marker::PhantomData;
|
|
/// #
|
|
/// # use serde::forward_to_deserialize_any;
|
|
/// # use serde::de::{value, Deserializer, Visitor};
|
|
/// #
|
|
/// # struct MyDeserializer<V>(PhantomData<V>);
|
|
/// #
|
|
/// # impl<'q, V> Deserializer<'q> for MyDeserializer<V> {
|
|
/// # type Error = value::Error;
|
|
/// #
|
|
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
|
|
/// # where
|
|
/// # W: Visitor<'q>,
|
|
/// # {
|
|
/// # unimplemented!()
|
|
/// # }
|
|
/// #
|
|
/// forward_to_deserialize_any! {
|
|
/// <W: Visitor<'q>>
|
|
/// bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
|
/// bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
|
/// tuple_struct map struct enum identifier ignored_any
|
|
/// }
|
|
/// # }
|
|
/// ```
|
|
///
|
|
/// [`Deserializer`]: trait.Deserializer.html
|
|
/// [`Visitor`]: de/trait.Visitor.html
|
|
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
|
|
#[macro_export(local_inner_macros)]
|
|
macro_rules! forward_to_deserialize_any {
|
|
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
|
|
$(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})*
|
|
};
|
|
// This case must be after the previous one.
|
|
($($func:ident)*) => {
|
|
$(forward_to_deserialize_any_helper!{$func<'de, V>})*
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export]
|
|
macro_rules! forward_to_deserialize_any_method {
|
|
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
|
|
#[inline]
|
|
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, Self::Error>
|
|
where
|
|
$v: $crate::de::Visitor<$l>,
|
|
{
|
|
$(
|
|
let _ = $arg;
|
|
)*
|
|
self.deserialize_any(visitor)
|
|
}
|
|
};
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
#[macro_export(local_inner_macros)]
|
|
macro_rules! forward_to_deserialize_any_helper {
|
|
(bool<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()}
|
|
};
|
|
(i8<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_i8<$l, $v>()}
|
|
};
|
|
(i16<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_i16<$l, $v>()}
|
|
};
|
|
(i32<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_i32<$l, $v>()}
|
|
};
|
|
(i64<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
|
|
};
|
|
(i128<$l:tt, $v:ident>) => {
|
|
serde_if_integer128! {
|
|
forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()}
|
|
}
|
|
};
|
|
(u8<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
|
|
};
|
|
(u16<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_u16<$l, $v>()}
|
|
};
|
|
(u32<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_u32<$l, $v>()}
|
|
};
|
|
(u64<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
|
|
};
|
|
(u128<$l:tt, $v:ident>) => {
|
|
serde_if_integer128! {
|
|
forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()}
|
|
}
|
|
};
|
|
(f32<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
|
|
};
|
|
(f64<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()}
|
|
};
|
|
(char<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_char<$l, $v>()}
|
|
};
|
|
(str<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_str<$l, $v>()}
|
|
};
|
|
(string<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_string<$l, $v>()}
|
|
};
|
|
(bytes<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_bytes<$l, $v>()}
|
|
};
|
|
(byte_buf<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_byte_buf<$l, $v>()}
|
|
};
|
|
(option<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_option<$l, $v>()}
|
|
};
|
|
(unit<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_unit<$l, $v>()}
|
|
};
|
|
(unit_struct<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_unit_struct<$l, $v>(name: &'static str)}
|
|
};
|
|
(newtype_struct<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)}
|
|
};
|
|
(seq<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_seq<$l, $v>()}
|
|
};
|
|
(tuple<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_tuple<$l, $v>(len: usize)}
|
|
};
|
|
(tuple_struct<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)}
|
|
};
|
|
(map<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_map<$l, $v>()}
|
|
};
|
|
(struct<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
|
|
};
|
|
(enum<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])}
|
|
};
|
|
(identifier<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_identifier<$l, $v>()}
|
|
};
|
|
(ignored_any<$l:tt, $v:ident>) => {
|
|
forward_to_deserialize_any_method!{deserialize_ignored_any<$l, $v>()}
|
|
};
|
|
}
|