messagepack_core/encode/
float.rs

1use super::{Encode, Result};
2use crate::{formats::Format, io::IoWrite};
3
4impl<W> Encode<W> for f32
5where
6    W: IoWrite,
7{
8    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
9        writer.write_bytes(&Format::Float32.as_slice())?;
10        writer.write_bytes(&self.to_be_bytes())?;
11        Ok(5)
12    }
13}
14
15impl<W> Encode<W> for f64
16where
17    W: IoWrite,
18{
19    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
20        writer.write_bytes(&Format::Float64.as_slice())?;
21        writer.write_bytes(&self.to_be_bytes())?;
22        Ok(9)
23    }
24}
25
26fn is_exactly_representable(x: f64) -> bool {
27    x.is_finite() && (x as f32) as f64 == x
28}
29
30/// encode minimum byte size
31#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
32pub enum EncodeMinimizeFloat {
33    F32(f32),
34    F64(f64),
35}
36
37impl From<f32> for EncodeMinimizeFloat {
38    fn from(value: f32) -> Self {
39        EncodeMinimizeFloat::F32(value)
40    }
41}
42
43impl From<f64> for EncodeMinimizeFloat {
44    fn from(value: f64) -> Self {
45        EncodeMinimizeFloat::F64(value)
46    }
47}
48
49impl<W> Encode<W> for EncodeMinimizeFloat
50where
51    W: IoWrite,
52{
53    fn encode(&self, writer: &mut W) -> Result<usize, <W as IoWrite>::Error> {
54        {
55            match self {
56                EncodeMinimizeFloat::F32(v) => v.encode(writer),
57                EncodeMinimizeFloat::F64(v) => {
58                    let v = *v;
59                    if is_exactly_representable(v) {
60                        (v as f32).encode(writer)
61                    } else {
62                        v.encode(writer)
63                    }
64                }
65            }
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    use rstest::rstest;
75
76    #[rstest]
77    #[case(123.456_f32,[Format::Float32.as_byte(), 0x42, 0xf6, 0xe9, 0x79])]
78    fn encode_float32<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
79        #[case] value: V,
80        #[case] expected: E,
81    ) {
82        let expected = expected.as_ref();
83
84        let mut buf = vec![];
85        let n = value.encode(&mut buf).unwrap();
86        assert_eq!(buf, expected);
87        assert_eq!(n, expected.len());
88    }
89
90    #[rstest]
91    #[case(123456.789_f64,[Format::Float64.as_byte(), 0x40, 0xfe, 0x24, 0x0c, 0x9f, 0xbe, 0x76, 0xc9])]
92    fn encode_float64<V: Encode<Vec<u8>>, E: AsRef<[u8]> + Sized>(
93        #[case] value: V,
94        #[case] expected: E,
95    ) {
96        let expected = expected.as_ref();
97
98        let mut buf = vec![];
99        let n = value.encode(&mut buf).unwrap();
100        assert_eq!(buf, expected);
101        assert_eq!(n, expected.len());
102    }
103
104    #[rstest]
105    #[case(1.0_f64, [Format::Float32.as_byte(), 0x3f, 0x80, 0x00, 0x00])]
106    #[case(1e39_f64, [Format::Float64.as_byte(), 0x48,0x07,0x82,0x87,0xf4,0x9c,0x4a,0x1d])]
107    fn encode_float_minimize<V: Into<EncodeMinimizeFloat>, E: AsRef<[u8]> + Sized>(
108        #[case] value: V,
109        #[case] expected: E,
110    ) {
111        let expected = expected.as_ref();
112        let encoder = value.into();
113
114        let mut buf = vec![];
115        let n = encoder.encode(&mut buf).unwrap();
116        assert_eq!(buf, expected);
117        assert_eq!(n, expected.len());
118    }
119}