use std::fmt;
use serde::ser::{self, Serialize};
#[derive(Debug)]
pub(crate) struct NonFiniteFloat;
impl fmt::Display for NonFiniteFloat {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("it contains NaN or an infinity, which JSON cannot represent")
}
}
impl std::error::Error for NonFiniteFloat {}
#[derive(Debug)]
pub(crate) enum CheckError {
NonFiniteFloat,
Other,
}
impl fmt::Display for CheckError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NonFiniteFloat => NonFiniteFloat.fmt(formatter),
Self::Other => formatter.write_str("the value cannot be serialized"),
}
}
}
impl std::error::Error for CheckError {}
impl ser::Error for CheckError {
fn custom<T: fmt::Display>(_message: T) -> Self {
Self::Other
}
}
pub(crate) fn check_finite_floats<Value: Serialize + ?Sized>(
value: &Value,
) -> Result<(), NonFiniteFloat> {
match value.serialize(FiniteCheck) {
Err(CheckError::NonFiniteFloat) => Err(NonFiniteFloat),
Ok(()) | Err(CheckError::Other) => Ok(()),
}
}
struct FiniteCheck;
fn check_float(finite: bool) -> Result<(), CheckError> {
if finite {
Ok(())
} else {
Err(CheckError::NonFiniteFloat)
}
}
impl ser::Serializer for FiniteCheck {
type Ok = ();
type Error = CheckError;
type SerializeSeq = Self;
type SerializeTuple = Self;
type SerializeTupleStruct = Self;
type SerializeTupleVariant = Self;
type SerializeMap = Self;
type SerializeStruct = Self;
type SerializeStructVariant = Self;
fn serialize_bool(self, _value: bool) -> Result<(), CheckError> {
Ok(())
}
fn serialize_i8(self, _value: i8) -> Result<(), CheckError> {
Ok(())
}
fn serialize_i16(self, _value: i16) -> Result<(), CheckError> {
Ok(())
}
fn serialize_i32(self, _value: i32) -> Result<(), CheckError> {
Ok(())
}
fn serialize_i64(self, _value: i64) -> Result<(), CheckError> {
Ok(())
}
fn serialize_i128(self, _value: i128) -> Result<(), CheckError> {
Ok(())
}
fn serialize_u8(self, _value: u8) -> Result<(), CheckError> {
Ok(())
}
fn serialize_u16(self, _value: u16) -> Result<(), CheckError> {
Ok(())
}
fn serialize_u32(self, _value: u32) -> Result<(), CheckError> {
Ok(())
}
fn serialize_u64(self, _value: u64) -> Result<(), CheckError> {
Ok(())
}
fn serialize_u128(self, _value: u128) -> Result<(), CheckError> {
Ok(())
}
fn serialize_f32(self, value: f32) -> Result<(), CheckError> {
check_float(value.is_finite())
}
fn serialize_f64(self, value: f64) -> Result<(), CheckError> {
check_float(value.is_finite())
}
fn serialize_char(self, _value: char) -> Result<(), CheckError> {
Ok(())
}
fn serialize_str(self, _value: &str) -> Result<(), CheckError> {
Ok(())
}
fn serialize_bytes(self, _value: &[u8]) -> Result<(), CheckError> {
Ok(())
}
fn serialize_none(self) -> Result<(), CheckError> {
Ok(())
}
fn serialize_some<Value: Serialize + ?Sized>(self, value: &Value) -> Result<(), CheckError> {
value.serialize(self)
}
fn serialize_unit(self) -> Result<(), CheckError> {
Ok(())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<(), CheckError> {
Ok(())
}
fn serialize_unit_variant(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
) -> Result<(), CheckError> {
Ok(())
}
fn serialize_newtype_struct<Value: Serialize + ?Sized>(
self,
_name: &'static str,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(self)
}
fn serialize_newtype_variant<Value: Serialize + ?Sized>(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(self)
}
fn serialize_seq(self, _length: Option<usize>) -> Result<Self, CheckError> {
Ok(self)
}
fn serialize_tuple(self, _length: usize) -> Result<Self, CheckError> {
Ok(self)
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_length: usize,
) -> Result<Self, CheckError> {
Ok(self)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
_length: usize,
) -> Result<Self, CheckError> {
Ok(self)
}
fn serialize_map(self, _length: Option<usize>) -> Result<Self, CheckError> {
Ok(self)
}
fn serialize_struct(self, _name: &'static str, _length: usize) -> Result<Self, CheckError> {
Ok(self)
}
fn serialize_struct_variant(
self,
_name: &'static str,
_index: u32,
_variant: &'static str,
_length: usize,
) -> Result<Self, CheckError> {
Ok(self)
}
}
impl ser::SerializeSeq for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_element<Value: Serialize + ?Sized>(
&mut self,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}
impl ser::SerializeTuple for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_element<Value: Serialize + ?Sized>(
&mut self,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}
impl ser::SerializeTupleStruct for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_field<Value: Serialize + ?Sized>(
&mut self,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}
impl ser::SerializeTupleVariant for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_field<Value: Serialize + ?Sized>(
&mut self,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}
impl ser::SerializeMap for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_key<Key: Serialize + ?Sized>(&mut self, key: &Key) -> Result<(), CheckError> {
key.serialize(FiniteCheck)
}
fn serialize_value<Value: Serialize + ?Sized>(
&mut self,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}
impl ser::SerializeStruct for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_field<Value: Serialize + ?Sized>(
&mut self,
_key: &'static str,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}
impl ser::SerializeStructVariant for FiniteCheck {
type Ok = ();
type Error = CheckError;
fn serialize_field<Value: Serialize + ?Sized>(
&mut self,
_key: &'static str,
value: &Value,
) -> Result<(), CheckError> {
value.serialize(FiniteCheck)
}
fn end(self) -> Result<(), CheckError> {
Ok(())
}
}