asterix/
custom_read_write.rs

1use deku::bitvec::{BitSlice, BitVec, Msb0};
2/// Several helpers for deku reading of certain types into certain types
3use deku::prelude::*;
4
5#[allow(dead_code)]
6pub(crate) enum Op {
7    Multiply,
8    Divide,
9    Add,
10    Subtract,
11}
12
13impl Op {
14    pub(crate) fn calculate(&self, value: f32, modifier: f32) -> f32 {
15        match self {
16            Op::Multiply => value * modifier,
17            Op::Divide => value / modifier,
18            Op::Add => value + modifier,
19            Op::Subtract => value - modifier,
20        }
21    }
22}
23
24pub(crate) mod read {
25    use super::*;
26
27    /// Read in big-endian bits to u32, multiply by f32, return f32
28    pub(crate) fn bits_to_f32(
29        rest: &BitSlice<u8, Msb0>,
30        bits: usize,
31        modifier: f32,
32        modifier_op: Op,
33    ) -> Result<(&BitSlice<u8, Msb0>, f32), DekuError> {
34        let (rest, value) = u32::read(rest, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))?;
35        Ok(op(rest, value as f32, modifier, modifier_op))
36    }
37
38    /// Read in big-endian bits to i16, multiply by f32, return f32
39    pub(crate) fn bits_i16_to_f32(
40        rest: &BitSlice<u8, Msb0>,
41        bits: usize,
42        modifier: f32,
43        modifier_op: Op,
44    ) -> Result<(&BitSlice<u8, Msb0>, f32), DekuError> {
45        let (rest, value) = i16::read(rest, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))?;
46        Ok(op(rest, f32::from(value), modifier, modifier_op))
47    }
48
49    pub(crate) fn op(
50        rest: &BitSlice<u8, Msb0>,
51        value: f32,
52        modifier: f32,
53        modifier_op: Op,
54    ) -> (&BitSlice<u8, Msb0>, f32) {
55        (rest, modifier_op.calculate(value, modifier))
56    }
57
58    /// Read in big-endian bits, multiply by f32, return Some(f32)
59    pub(crate) fn bits_to_optionf32(
60        rest: &BitSlice<u8, Msb0>,
61        bits: usize,
62        modifier: f32,
63        modifier_op: Op,
64    ) -> Result<(&BitSlice<u8, Msb0>, Option<f32>), DekuError> {
65        bits_to_f32(rest, bits, modifier, modifier_op).map(|(rest, f)| (rest, Some(f)))
66    }
67}
68
69pub mod write {
70    use super::*;
71
72    pub(crate) fn f32_u32(
73        value: &f32,
74        bits: usize,
75        modifier: f32,
76        modifier_op: Op,
77        output: &mut BitVec<u8, Msb0>,
78    ) -> Result<(), DekuError> {
79        // TODO this should be function for this and the other one
80        let value = modifier_op.calculate(*value, modifier);
81        (value as u32).write(output, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))
82    }
83
84    pub(crate) fn f32_optionu32(
85        value: &Option<f32>,
86        bits: usize,
87        modifier: f32,
88        modifier_op: Op,
89        output: &mut BitVec<u8, Msb0>,
90    ) -> Result<(), DekuError> {
91        value.map_or(Ok(()), |value| f32_u32(&value, bits, modifier, modifier_op, output))
92    }
93
94    pub(crate) fn f32_i32(
95        value: &f32,
96        bits: usize,
97        modifier: f32,
98        modifier_op: Op,
99        output: &mut BitVec<u8, Msb0>,
100    ) -> Result<(), DekuError> {
101        let value = modifier_op.calculate(*value, modifier);
102        (value as i32).write(output, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))
103    }
104}