use crate::components::sparse_enum;
use crate::types::RangedU8;
use nord_bits_derive::bitbody;
#[bitbody(8)]
#[derive(Default)]
pub struct PianoPanel {
#[bits(0..=2)]
pub category: PianoCategory,
#[bits(5..=9)]
pub piano_model: RangedU8<31>,
#[bits(15..=16)]
pub clav_model: RangedU8<3>,
#[bits(17..=18)]
pub acoustics: RangedU8<3>,
#[bits(19..=20)]
pub touch: RangedU8<3>,
#[bits(21..=21)]
pub mono: bool,
#[bits(22..=53)]
pub id: u32,
}
sparse_enum!(
PianoCategory, 3, {
0 => Grand, "grand";
1 => Upright, "upright";
2 => EPiano1, "epiano1";
3 => EPiano2, "epiano2";
4 => Clavinet, "clavinet";
5 => Harpsichord, "harps";
}
);
#[cfg(test)]
mod tests {
use super::*;
use std::array;
#[test]
fn unnamed_bits_survive_a_re_encode() {
const GAPS: [u8; 8] = [0b0001_1000, 0b0011_1110, 0, 0, 0, 0, 0, 0];
fn gap_bits(raw: [u8; 8]) -> [u8; 8] {
array::from_fn(|i| raw[i] & GAPS[i])
}
let mut panel = PianoPanel::try_from(GAPS).unwrap();
panel.category = PianoCategory::EPiano1;
panel.id = 0xdead_beef;
let out = <[u8; 8]>::from(&panel);
assert_eq!(gap_bits(out), GAPS, "a re-encode cleared a gap bit");
let mut panel = PianoPanel::try_from([0; 8]).unwrap();
panel.category = PianoCategory::Unknown(7);
panel.piano_model = 31u8.try_into().unwrap();
let out = <[u8; 8]>::from(&panel);
assert_eq!(gap_bits(out), [0; 8], "a re-encode set a gap bit");
}
}