use crate::enum_wrapper;
use enum2repr::EnumRepr;
#[repr(u8)]
#[derive(EnumRepr, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[deprecated(
note = "The `auto_uds` crate has been renamed to `automotive_diag`. Update your Cargo.toml, and use this enum from the `uds` namespace."
)]
pub enum ScalingType {
UnsignedNumeric = 0x00,
SignedNumeric = 0x10,
BitMappingWithoutMask = 0x20,
BitMappingWithMask = 0x30,
Bcd = 0x40,
StateEncodedVariable = 0x50,
Ascii = 0x60,
SignedFloatingPoint = 0x70,
Packet = 0x80,
Formula = 0x90,
UnitOrFormat = 0xA0,
StateAndConnectionType = 0xB0,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Scaling {
typ: ScalingType,
size: u8,
}
impl From<Scaling> for u8 {
fn from(value: Scaling) -> Self {
value.typ as u8 | value.size
}
}
enum_wrapper!(Scaling, ScalingByte);
impl Scaling {
pub fn new(typ: ScalingType, size: u8) -> Result<Self, &'static str> {
if size > 0x0F {
return Err("Invalid size, expecting between 0 and 15.");
}
(typ as u8 | size).try_into()
}
}
impl TryFrom<u8> for Scaling {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
let typ: ScalingType = (value & 0xF0).try_into()?;
let size = value & 0x0F;
match typ {
ScalingType::UnsignedNumeric | ScalingType::SignedNumeric => {
if !(1..=4).contains(&size) {
return Err("Invalid number of data bytes for a numeric type, expecting between 1 and 4.");
}
}
ScalingType::Ascii => {
if !(1..=15).contains(&size) {
return Err(
"Invalid number of data bytes for ASCII type, expecting between 1 and 15.",
);
}
}
_ => {
if size != 0 {
return Err("No data bytes are expected for this type.");
}
}
};
Ok(Self { typ, size })
}
}
#[cfg(test)]
mod tests2 {
use super::*;
#[test]
fn test_scaling_byte() {
use ScalingType::*;
assert_eq!(u8::from(Scaling::new(SignedNumeric, 4).unwrap()), 0x14);
assert_eq!(u8::from(Scaling::new(SignedNumeric, 1).unwrap()), 0x11);
assert!(Scaling::new(SignedNumeric, 0).is_err());
assert!(Scaling::new(Bcd, 1).is_err());
}
}