use der::{Decode, Encode, Reader, Writer};
use crate::math::Vector3;
use super::{FovShape, Instrument};
impl FovShape {
fn variant(&self) -> u8 {
match self {
Self::Conical { .. } => 0,
Self::Rectangular { .. } => 1,
}
}
}
impl Encode for FovShape {
fn encoded_len(&self) -> der::Result<der::Length> {
self.variant().encoded_len()?
+ match self {
Self::Conical { half_angle_deg } => {
(half_angle_deg.encoded_len()? + f64::NAN.encoded_len()?)?
}
Self::Rectangular {
x_half_angle_deg,
y_half_angle_deg,
} => (x_half_angle_deg.encoded_len()? + y_half_angle_deg.encoded_len()?)?,
}
}
fn encode(&self, encoder: &mut impl Writer) -> der::Result<()> {
self.variant().encode(encoder)?;
match self {
Self::Conical { half_angle_deg } => {
half_angle_deg.encode(encoder)?;
f64::NAN.encode(encoder)
}
Self::Rectangular {
x_half_angle_deg,
y_half_angle_deg,
} => {
x_half_angle_deg.encode(encoder)?;
y_half_angle_deg.encode(encoder)
}
}
}
}
impl<'a> Decode<'a> for FovShape {
fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
let variant: u8 = decoder.decode()?;
Ok(match variant {
0 => {
let half_angle_deg = decoder.decode()?;
let _: f64 = decoder.decode()?;
Self::Conical { half_angle_deg }
}
1 => {
let x_half_angle_deg = decoder.decode()?;
let y_half_angle_deg = decoder.decode()?;
Self::Rectangular {
x_half_angle_deg,
y_half_angle_deg,
}
}
_ => Self::default(),
})
}
}
impl Encode for Instrument {
fn encoded_len(&self) -> der::Result<der::Length> {
self.q_to_i.encoded_len()?
+ self.offset_i.x.encoded_len()?
+ self.offset_i.y.encoded_len()?
+ self.offset_i.z.encoded_len()?
+ self.fov.encoded_len()?
}
fn encode(&self, encoder: &mut impl Writer) -> der::Result<()> {
self.q_to_i.encode(encoder)?;
self.offset_i.x.encode(encoder)?;
self.offset_i.y.encode(encoder)?;
self.offset_i.z.encode(encoder)?;
self.fov.encode(encoder)
}
}
impl<'a> Decode<'a> for Instrument {
fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
let q_to_i = decoder.decode()?;
let x = decoder.decode()?;
let y = decoder.decode()?;
let z = decoder.decode()?;
let fov = decoder.decode()?;
Ok(Self {
q_to_i,
offset_i: Vector3::new(x, y, z),
fov,
})
}
}
#[cfg(test)]
mod instrument_encdec {
use crate::math::rotation::EulerParameter;
use super::*;
#[test]
fn conical() {
let repr = Instrument {
q_to_i: EulerParameter::about_x(core::f64::consts::FRAC_2_SQRT_PI, 1, 2),
offset_i: Vector3::new(1.0, 2.0, 3.0),
fov: FovShape::Conical {
half_angle_deg: 12.3,
},
};
let mut buf = vec![];
repr.encode_to_vec(&mut buf).unwrap();
let repr_dec = Instrument::from_der(&buf).unwrap();
assert_eq!(repr_dec, repr);
}
#[test]
fn rect() {
let repr = Instrument {
q_to_i: EulerParameter::about_x(core::f64::consts::FRAC_2_SQRT_PI, 1, 2),
offset_i: Vector3::new(1.0, 2.0, 3.0),
fov: FovShape::Rectangular {
x_half_angle_deg: 12.3,
y_half_angle_deg: 13.9,
},
};
let mut buf = vec![];
repr.encode_to_vec(&mut buf).unwrap();
let repr_dec = Instrument::from_der(&buf).unwrap();
assert_eq!(repr_dec, repr);
}
}