Skip to main content

ic_wire/float/
mod.rs

1use crate::{Error, Shape, Wire, schema::Schema};
2use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
3
4macro_rules! finite {
5    ($name:ident, $primitive:ty, $bits:literal) => {
6        /// A finite IEEE-754 value encoded in Postcard's native little-endian form.
7        ///
8        /// NaN and infinity are rejected. All finite bits, including negative zero
9        /// and subnormals, are preserved. Consumer normalization remains separate.
10        #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
11        pub struct $name($primitive);
12        impl $name {
13            /// Admit a finite value; non-finite input returns Error::Malformed.
14            pub fn new(value: $primitive) -> Result<Self, Error> {
15                if value.is_finite() {
16                    Ok(Self(value))
17                } else {
18                    Err(Error::Malformed)
19                }
20            }
21            /// Recover the exact admitted primitive value.
22            pub fn get(self) -> $primitive {
23                self.0
24            }
25        }
26        impl Serialize for $name {
27            fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
28                self.0.serialize(serializer)
29            }
30        }
31        impl<'de> Deserialize<'de> for $name {
32            fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33                Self::new(<$primitive>::deserialize(deserializer)?)
34                    .map_err(|_| de::Error::custom("non-finite float"))
35            }
36        }
37        impl Wire for $name {
38            const SHAPE: Shape = Shape::scalar($bits / 8);
39            const SCHEMA: Schema = Schema::Float($bits);
40        }
41    };
42}
43finite!(FiniteF32, f32, 32);
44finite!(FiniteF64, f64, 64);