use num_enum::{IntoPrimitive, TryFromPrimitive};
use serde::{Deserialize, Serialize};
use strum::VariantArray;
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
IntoPrimitive,
TryFromPrimitive,
VariantArray,
)]
#[repr(u32)]
pub enum NumberFormat {
Binary = 0x1,
Octal = 0x2,
Hexadecimal = 0x3,
Decimal = 0x4,
Char = 0x6,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[doc(alias("value_repr_t"))]
pub struct ValueRepr {
pub format: NumberFormat,
pub signed: bool,
pub leading_zeros: bool,
}
#[cfg(test)]
mod tests {
use assert2::assert;
use idakit_sys as sys;
use rstest::rstest;
use super::*;
#[rstest]
#[case(NumberFormat::Binary, 0x1)]
#[case(NumberFormat::Octal, 0x2)]
#[case(NumberFormat::Hexadecimal, 0x3)]
#[case(NumberFormat::Decimal, 0x4)]
#[case(NumberFormat::Char, 0x6)]
fn number_format_round_trips_and_pins_frb(#[case] format: NumberFormat, #[case] frb: u32) {
assert!(u32::from(format) == frb);
assert!(NumberFormat::try_from(frb) == Ok(format));
}
#[test]
fn frb_vtype_ids_align_with_the_facade() {
let ids = sys::frb_vtype_ids();
assert!(
ids.len() == NumberFormat::VARIANTS.len(),
"facade lists {} ids for {} variants",
ids.len(),
NumberFormat::VARIANTS.len()
);
for (i, &format) in NumberFormat::VARIANTS.iter().enumerate() {
assert!(
ids[i] == u32::from(format),
"number format {format:?}: facade FRB_ {} != discriminant {}",
ids[i],
u32::from(format)
);
}
}
#[test]
fn every_variant_round_trips() {
for &format in NumberFormat::VARIANTS {
assert!(NumberFormat::try_from(u32::from(format)) == Ok(format));
}
}
#[rstest]
#[case::unk(0x0)]
#[case::float(0x5)]
#[case::seg(0x7)]
#[case::enum_linked(0x8)]
#[case::out_of_range(0xff)]
fn try_from_rejects_unmodeled(#[case] vtype: u32) {
assert!(NumberFormat::try_from(vtype).is_err());
}
}