use crate::{Error, Shape, Wire, schema::Schema};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
macro_rules! finite {
($name:ident, $primitive:ty, $bits:literal) => {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct $name($primitive);
impl $name {
pub fn new(value: $primitive) -> Result<Self, Error> {
if value.is_finite() {
Ok(Self(value))
} else {
Err(Error::Malformed)
}
}
pub fn get(self) -> $primitive {
self.0
}
}
impl Serialize for $name {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for $name {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Self::new(<$primitive>::deserialize(deserializer)?)
.map_err(|_| de::Error::custom("non-finite float"))
}
}
impl Wire for $name {
const SHAPE: Shape = Shape::scalar($bits / 8);
const SCHEMA: Schema = Schema::Float($bits);
}
};
}
finite!(FiniteF32, f32, 32);
finite!(FiniteF64, f64, 64);