use core::num::FpCategory;
use crate::{Read, Stack, JsonError, Value, JsonDeserialize, JsonSerialize};
impl JsonDeserialize for f64 {
fn deserialize<'read, 'parent, B: Read<'read>, S: Stack>(
value: Value<'read, 'parent, B, S>,
) -> Result<Self, JsonError<'read, B, S>> {
value.to_number()?.f64().ok_or(JsonError::TypeError)
}
}
#[derive(Clone, Copy, Default, Debug)]
pub struct JsonF64(f64);
impl TryFrom<f64> for JsonF64 {
type Error = FpCategory;
fn try_from(value: f64) -> Result<Self, Self::Error> {
let class = value.classify();
match class {
FpCategory::Nan | FpCategory::Infinite => Err(class)?,
FpCategory::Zero | FpCategory::Normal | FpCategory::Subnormal => {}
}
Ok(Self(value))
}
}
impl From<JsonF64> for f64 {
fn from(value: JsonF64) -> f64 {
value.0
}
}
impl JsonDeserialize for JsonF64 {
fn deserialize<'read, 'parent, B: Read<'read>, S: Stack>(
value: Value<'read, 'parent, B, S>,
) -> Result<Self, JsonError<'read, B, S>> {
JsonF64::try_from(f64::deserialize(value)?).map_err(|_| JsonError::TypeError)
}
}
#[cfg(not(feature = "ryu"))]
mod serialize {
use core::fmt::Write;
use crate::NumberSink;
use super::*;
impl JsonSerialize for JsonF64 {
fn serialize(&self) -> impl Iterator<Item = char> {
let mut sink = NumberSink::new();
write!(&mut sink, "{}", self.0).expect("infallible `NumberSink` raised an error");
let (buf, len) = sink.imprecise_str().expect("`NumberSink` couldn't sink a `f64` from Rust");
buf.into_iter().take(len).map(|b| b as char)
}
}
}
#[cfg(feature = "ryu")]
mod serialize {
use super::*;
impl JsonSerialize for JsonF64 {
fn serialize(&self) -> impl Iterator<Item = char> {
let mut buffer = ryu::Buffer::new();
let result = buffer.format_finite(self.0).as_bytes();
let mut owned = [0; core::mem::size_of::<ryu::Buffer>()];
owned[.. result.len()].copy_from_slice(result);
owned.into_iter().take(result.len()).map(|byte| byte as char)
}
}
}