use deku::bitvec::{BitSlice, BitVec, Msb0};
use deku::prelude::*;
#[allow(dead_code)]
pub(crate) enum Op {
Multiply,
Divide,
Add,
Subtract,
}
impl Op {
pub(crate) fn calculate(&self, value: f32, modifier: f32) -> f32 {
match self {
Op::Multiply => value * modifier,
Op::Divide => value / modifier,
Op::Add => value + modifier,
Op::Subtract => value - modifier,
}
}
}
pub(crate) mod read {
use super::*;
pub(crate) fn bits_to_f32(
rest: &BitSlice<u8, Msb0>,
bits: usize,
modifier: f32,
modifier_op: Op,
) -> Result<(&BitSlice<u8, Msb0>, f32), DekuError> {
let (rest, value) = u32::read(rest, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))?;
Ok(op(rest, value as f32, modifier, modifier_op))
}
pub(crate) fn bits_i16_to_f32(
rest: &BitSlice<u8, Msb0>,
bits: usize,
modifier: f32,
modifier_op: Op,
) -> Result<(&BitSlice<u8, Msb0>, f32), DekuError> {
let (rest, value) = i16::read(rest, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))?;
Ok(op(rest, f32::from(value), modifier, modifier_op))
}
pub(crate) fn op(
rest: &BitSlice<u8, Msb0>,
value: f32,
modifier: f32,
modifier_op: Op,
) -> (&BitSlice<u8, Msb0>, f32) {
(rest, modifier_op.calculate(value, modifier))
}
pub(crate) fn bits_to_optionf32(
rest: &BitSlice<u8, Msb0>,
bits: usize,
modifier: f32,
modifier_op: Op,
) -> Result<(&BitSlice<u8, Msb0>, Option<f32>), DekuError> {
bits_to_f32(rest, bits, modifier, modifier_op).map(|(rest, f)| (rest, Some(f)))
}
}
pub mod write {
use super::*;
pub(crate) fn f32_u32(
value: &f32,
bits: usize,
modifier: f32,
modifier_op: Op,
output: &mut BitVec<u8, Msb0>,
) -> Result<(), DekuError> {
let value = modifier_op.calculate(*value, modifier);
(value as u32).write(output, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))
}
pub(crate) fn f32_optionu32(
value: &Option<f32>,
bits: usize,
modifier: f32,
modifier_op: Op,
output: &mut BitVec<u8, Msb0>,
) -> Result<(), DekuError> {
value.map_or(Ok(()), |value| f32_u32(&value, bits, modifier, modifier_op, output))
}
pub(crate) fn f32_i32(
value: &f32,
bits: usize,
modifier: f32,
modifier_op: Op,
output: &mut BitVec<u8, Msb0>,
) -> Result<(), DekuError> {
let value = modifier_op.calculate(*value, modifier);
(value as i32).write(output, (deku::ctx::Endian::Big, deku::ctx::BitSize(bits)))
}
}