macro_rules! str_mod {
(
$mod_name:ident,
$optional_mod_name:ident,
$ty:ident
) => {
macro_rules! visit_method {
(
$method_type:ident,
$method_name:ident,
$from_method:ident,
$surround:expr,
$group:ident,
$group_ty:ident
) => {
#[inline]
fn $method_name <E>(self, value: $method_type) -> Result<Self::Value, E>
where
E: Error,
{
match ::num::cast::FromPrimitive::$from_method(value) {
Some(v) => Ok($surround(v)),
None => Err(Error::invalid_value(Unexpected::$group(value as $group_ty), &self))
}
}
}
}
#[allow(dead_code)]
pub mod $mod_name {
use serde::{Deserializer, Serializer, Serialize};
use std::fmt;
use serde::de::{Error, Unexpected, Visitor};
struct StringOrNumberVisitor;
impl<'de> Visitor<'de> for StringOrNumberVisitor {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!(stringify!($ty), " or string containing ", stringify!($ty)))
}
#[inline]
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
value
.parse()
.map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
}
visit_method!(i8, visit_i8, from_i8, |x| x, Signed, i64);
visit_method!(i16, visit_i16, from_i16, |x| x, Signed, i64);
visit_method!(i32, visit_i32, from_i32, |x| x, Signed, i64);
visit_method!(i64, visit_i64, from_i64, |x| x, Signed, i64);
visit_method!(u8, visit_u8, from_u8, |x| x, Unsigned, u64);
visit_method!(u16, visit_u16, from_u16, |x| x, Unsigned, u64);
visit_method!(u32, visit_u32, from_u32, |x| x, Unsigned, u64);
visit_method!(u64, visit_u64, from_u64, |x| x, Unsigned, u64);
}
pub fn serialize<S>(data: &i64, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
data.serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<$ty, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(StringOrNumberVisitor)
}
}
#[allow(dead_code)]
pub mod $optional_mod_name {
use serde::{Deserializer, Serializer, Serialize};
use std::fmt;
use serde::de::{Error, Unexpected, Visitor};
struct OptionalStringOrNumberVisitor;
impl<'de> Visitor<'de> for OptionalStringOrNumberVisitor {
type Value = Option<$ty>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an integer or string containing an integer")
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
Ok(None)
}
#[inline]
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
value
.parse()
.map(Some)
.map_err(|_| E::invalid_value(Unexpected::Str(value), &self))
}
visit_method!(i8, visit_i8, from_i8, Some, Signed, i64);
visit_method!(i16, visit_i16, from_i16, Some, Signed, i64);
visit_method!(i32, visit_i32, from_i32, Some, Signed, i64);
visit_method!(i64, visit_i64, from_i64, Some, Signed, i64);
visit_method!(u8, visit_u8, from_u8, Some, Unsigned, u64);
visit_method!(u16, visit_u16, from_u16, Some, Unsigned, u64);
visit_method!(u32, visit_u32, from_u32, Some, Unsigned, u64);
visit_method!(u64, visit_u64, from_u64, Some, Unsigned, u64);
}
pub fn serialize<S>(data: &Option<$ty>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *data {
Some(ref d) => d.serialize(serializer),
None => serializer.serialize_unit(),
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<$ty>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(OptionalStringOrNumberVisitor)
}
}
}
}
str_mod!(u32_or_str_containing, optional_u32_or_str_containing, u32);