lilliput_core/decoder/
float.rs

1use lilliput_float::{FpExtend as _, FpFromBeBytes as _, F16, F24, F32, F40, F48, F56, F64, F8};
2
3use crate::{error::Result, header::FloatHeader, marker::Marker, value::FloatValue};
4
5use super::{Decoder, Read};
6
7impl<'de, R> Decoder<R>
8where
9    R: Read<'de>,
10{
11    // MARK: - Value
12
13    /// Decodes a 32-bit floating-point value.
14    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
15    pub fn decode_f32(&mut self) -> Result<f32> {
16        let header = self.decode_float_header()?;
17        Ok(self.decode_float_value_of(header)?.into())
18    }
19
20    /// Decodes a 64-bit floating-point value.
21    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
22    pub fn decode_f64(&mut self) -> Result<f64> {
23        let header = self.decode_float_header()?;
24        Ok(self.decode_float_value_of(header)?.into())
25    }
26
27    /// Decodes a floating-point value, as a `FloatValue`.
28    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
29    pub fn decode_float_value(&mut self) -> Result<FloatValue> {
30        let header = self.decode_float_header()?;
31
32        self.decode_float_value_of(header)
33    }
34
35    // MARK: - Header
36
37    /// Decodes a floating-point value's header.
38    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
39    pub fn decode_float_header(&mut self) -> Result<FloatHeader> {
40        let byte = self.pull_byte_expecting(Marker::Float)?;
41
42        let width = 1 + (byte & FloatHeader::VALUE_WIDTH_BITS);
43
44        #[cfg(feature = "tracing")]
45        tracing::debug!(byte = crate::binary::fmt_byte(byte), width = width);
46
47        Ok(FloatHeader::new(width))
48    }
49
50    // MARK: - Skip
51
52    /// Skips the floating-point value for a given `header`.
53    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
54    pub fn skip_float_value_of(&mut self, header: FloatHeader) -> Result<()> {
55        self.reader.skip(header.width().into())
56    }
57
58    // MARK: - Body
59
60    /// Decodes floating-point value for a given `header`, as a `FloatValue`.
61    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
62    pub fn decode_float_value_of(&mut self, header: FloatHeader) -> Result<FloatValue> {
63        match header.width() {
64            1 => {
65                let mut bytes: [u8; 1] = [0b0; 1];
66                self.pull_bytes_into(&mut bytes)?;
67                let packed = F8::from_be_bytes(bytes);
68                let unpacked: F32 = packed.extend();
69                Ok(FloatValue::F32(unpacked.into()))
70            }
71            2 => {
72                let mut bytes: [u8; 2] = [0b0; 2];
73                self.pull_bytes_into(&mut bytes)?;
74                let packed = F16::from_be_bytes(bytes);
75                let unpacked: F32 = packed.extend();
76                Ok(FloatValue::F32(unpacked.into()))
77            }
78            3 => {
79                let mut bytes: [u8; 3] = [0b0; 3];
80                self.pull_bytes_into(&mut bytes)?;
81                let packed = F24::from_be_bytes(bytes);
82                let unpacked: F32 = packed.extend();
83                Ok(FloatValue::F32(unpacked.into()))
84            }
85            4 => {
86                let mut bytes: [u8; 4] = [0b0; 4];
87                self.pull_bytes_into(&mut bytes)?;
88                let value = F32::from_be_bytes(bytes);
89                Ok(FloatValue::F32(value.into()))
90            }
91            5 => {
92                let mut bytes: [u8; 5] = [0b0; 5];
93                self.pull_bytes_into(&mut bytes)?;
94                let packed = F40::from_be_bytes(bytes);
95                let unpacked: F64 = packed.extend();
96                Ok(FloatValue::F64(unpacked.into()))
97            }
98            6 => {
99                let mut bytes: [u8; 6] = [0b0; 6];
100                self.pull_bytes_into(&mut bytes)?;
101                let packed = F48::from_be_bytes(bytes);
102                let unpacked: F64 = packed.extend();
103                Ok(FloatValue::F64(unpacked.into()))
104            }
105            7 => {
106                let mut bytes: [u8; 7] = [0b0; 7];
107                self.pull_bytes_into(&mut bytes)?;
108                let packed = F56::from_be_bytes(bytes);
109                let unpacked: F64 = packed.extend();
110                Ok(FloatValue::F64(unpacked.into()))
111            }
112            8 => {
113                let mut bytes: [u8; 8] = [0b0; 8];
114                self.pull_bytes_into(&mut bytes)?;
115                let value = F64::from_be_bytes(bytes);
116                Ok(FloatValue::F64(value.into()))
117            }
118            _ => unreachable!(),
119        }
120    }
121}