use std::{fmt::Formatter, ops::Neg, str::FromStr};
use cast::i32;
use derive_more::{DebugCustom, Display};
use ordered_float::OrderedFloat;
use serde::{serde_if_integer128, Deserialize, Deserializer, Serialize, Serializer};
pub(crate) type PrimitiveReal = f64;
#[derive(
Copy,
Clone,
Eq,
PartialEq,
Ord,
PartialOrd,
Hash,
DebugCustom,
Display,
num_derive::FromPrimitive,
num_derive::ToPrimitive,
num_derive::NumCast,
num_derive::NumOps,
num_derive::Zero,
num_derive::One,
num_derive::Num,
num_derive::Float,
)]
#[debug(fmt = "{_0}")]
#[display(fmt = "{_0}")]
pub struct Number(OrderedFloat<PrimitiveReal>);
impl Number {
pub(crate) fn to_primitive_real(self) -> PrimitiveReal {
self.0 .0
}
}
impl FromStr for Number {
type Err = <PrimitiveReal as FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
PrimitiveReal::from_str(s).map(|n| Number(OrderedFloat(n)))
}
}
impl Neg for Number {
type Output = Self;
fn neg(self) -> Self::Output {
Self(-self.0)
}
}
impl<T> From<T> for Number
where
PrimitiveReal: cast::From<T, Output = PrimitiveReal>,
{
fn from(v: T) -> Self {
use cast::From;
Self(OrderedFloat(PrimitiveReal::cast(v)))
}
}
impl Serialize for Number {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
#[allow(clippy::float_cmp)]
if self.0 .0.trunc() == self.0 .0 {
if let Ok(v) = i32(self.0 .0) {
return serializer.serialize_i32(v);
}
}
serializer.serialize_f64(self.0 .0)
}
}
impl<'de> Deserialize<'de> for Number {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct V;
impl<'de> serde::de::Visitor<'de> for V {
type Value = Number;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(formatter, "null, number")
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.into())
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.into())
}
serde_if_integer128! {
fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.into())
}
fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.into())
}
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.into())
}
}
deserializer.deserialize_any(V)
}
}