Skip to main content

substrate_data/schema/plain/
floats.rs

1//! The schemas of floats: raw in frames, `f32`-exact lists narrowed.
2
3use crate::binary::{Decoder, Writer};
4use crate::frame::{Packer, Unpacker};
5use crate::model::borrowed::ValueRef;
6use crate::model::value::Value;
7use crate::schema::{Expected, Reader, Schema, Shape};
8
9/// What a schema needs of a float type: its width, and the model's `f64`
10/// both ways.
11trait Float: Copy {
12    /// Its width in bits.
13    const BITS: u32;
14    /// From the model's `f64` (an `f32` rounded to the nearest).
15    fn of_f64(f: f64) -> Self;
16    /// As the model's `f64`.
17    fn to_f64(self) -> f64;
18}
19
20impl Float for f32 {
21    const BITS: u32 = 32;
22    #[expect(
23        clippy::cast_possible_truncation,
24        reason = "a number read as an f32 is rounded to one"
25    )]
26    fn of_f64(f: f64) -> Self {
27        f as f32
28    }
29    fn to_f64(self) -> f64 {
30        f64::from(self)
31    }
32}
33
34impl Float for f64 {
35    const BITS: u32 = 64;
36    fn of_f64(f: f64) -> Self {
37        f
38    }
39    fn to_f64(self) -> f64 {
40        self
41    }
42}
43
44macro_rules! float_schema {
45    ($($t:ty => $one:ident, $many:ident, $read_many:ident, $put:ident, $get:ident, $puts:ident, $gets:ident);*) => {$(
46        impl Schema for $t {
47            fn shape() -> Shape {
48                Shape::Float { bits: <$t as Float>::BITS }
49            }
50            fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
51                v.as_f64().map(<$t as Float>::of_f64).or_else(|| {
52                    cx.expected(Expected::Number, v);
53                    None
54                })
55            }
56            fn write(&self) -> Value {
57                Value::Float(self.to_f64())
58            }
59            fn encode(&self, w: &mut Writer) {
60                w.$one(*self);
61            }
62            fn decode(d: &mut Decoder<'_>) -> Option<Self> {
63                d.float().map(<$t as Float>::of_f64)
64            }
65            fn write_text(&self, w: &mut crate::text::Writer) {
66                w.float(self.to_f64());
67            }
68            fn encode_list(items: &[Self], w: &mut Writer) {
69                w.$many(items);
70            }
71            fn decode_list(d: &mut Decoder<'_>) -> Option<Vec<Self>> {
72                d.$read_many()
73            }
74            fn pack(&self, p: &mut Packer) {
75                p.$put(*self);
76            }
77            fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
78                u.$get()
79            }
80            fn pack_list(items: &[Self], p: &mut Packer) {
81                p.$puts(items);
82            }
83            fn unpack_list(u: &mut Unpacker<'_>) -> Option<Vec<Self>> {
84                u.$gets()
85            }
86        }
87    )*};
88}
89float_schema!(
90    f32 => float32, floats32, floats32, put_f32, f32, put_f32s, f32s;
91    f64 => float, floats, floats, put_f64, f64, put_f64s, f64s
92);