macro_rules! impl_serialize_as {
($t: ty, $ser_fn: ident) => {
fn serialize_as<S>(value: &$t, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
match value {
x if x.is_nan() => serializer.serialize_str("NaN"),
x if x.is_infinite() && x.is_sign_negative() => {
serializer.serialize_str("-Infinity")
}
x if x.is_infinite() => serializer.serialize_str("Infinity"),
x => serializer.$ser_fn(*x),
}
}
};
}
macro_rules! impl_visitor {
($name: ident, $t: ty, $msg: literal) => {
struct $name;
impl serde::de::Visitor<'_> for $name {
type Value = $t;
fn visit_str<E>(self, value: &str) -> std::result::Result<Self::Value, E>
where
E: serde::de::Error,
{
match value {
"NaN" => Ok(<$t>::NAN),
"Infinity" => Ok(<$t>::INFINITY),
"-Infinity" => Ok(<$t>::NEG_INFINITY),
_ => self.visit_f64(value.parse::<f64>().map_err(E::custom)?),
}
}
fn visit_i64<E>(self, value: i64) -> std::result::Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(value as Self::Value)
}
fn visit_u64<E>(self, value: u64) -> std::result::Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(value as Self::Value)
}
fn visit_f64<E>(self, value: f64) -> std::result::Result<Self::Value, E>
where
E: serde::de::Error,
{
match value {
_ if value < <$t>::MIN as f64 => Err(self::value_error(value, $msg)),
_ if value > <$t>::MAX as f64 => Err(self::value_error(value, $msg)),
_ => Ok(value as Self::Value),
}
}
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str($msg)
}
}
};
}
#[cfg(test)]
macro_rules! impl_assert_float_eq {
($fn: ident, $t: ty) => {
fn $fn(left: $t, right: $t) {
if left.is_nan() && right.is_nan() {
return;
}
if left.is_infinite()
&& right.is_infinite()
&& left.is_sign_positive() == right.is_sign_positive()
{
return;
}
assert_eq!(left, right);
}
};
}