use super::{Display, Frame, ParseError};
bitflags::bitflags! {
#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(align(8))]
#[derive(Display)]
pub struct Buttons: u16 {
const DPAD_LEFT = 0b00000000_00000001;
const MYSTERY_BTN_0 = 0b00000000_00000010;
const DPAD_DOWN = 0b00000000_00000100;
const MYSTERY_BTN_1 = 0b00000000_00001000;
const DPAD_UP = 0b00000000_00010000;
const MYSTERY_BTN_2 = 0b00000000_00100000;
const DPAD_RIGHT = 0b00000000_01000000;
const MYSTERY_BTN_3 = 0b00000000_10000000;
const BACK_INPUT_BUTTON = 0b00000001_00000000;
const MYSTERY_BTN_4 = 0b00000010_00000000;
const BACK_VOL_UP = 0b00000100_00000000;
const BACK_VOL_DOWN = 0b00001000_00000000;
const BACK_TRACK_SKIP = 0b00010000_00000000;
const BACK_TRACK_REWIND = 0b00100000_00000000;
const BACK_SEEK_BUTTON = 0b01000000_00000000;
const MYSTERY_BTN_5 = 0b10000000_00000000;
const STOCK_BUTTONS = 0b01111101_01010101;
}
}
impl Buttons {
pub const fn stock_buttons_pressed(self) -> Self {
self.intersection(Self::STOCK_BUTTONS)
}
}
impl TryFrom<Frame> for Buttons {
type Error = ParseError;
fn try_from(frame: Frame) -> Result<Self, Self::Error> {
const ID: u32 = 0x318;
const LEN: usize = 8;
if frame.id() != ID {
return Err(ParseError::Id { frame });
}
let data: [u8; LEN] = match frame.data().try_into() {
Ok(data) => data,
Err(_) => {
return Err(ParseError::Len {
frame,
expected: LEN,
})
}
};
match Buttons::from_bits(u16::from_be_bytes([data[3], data[4]])) {
Some(dpad) => Ok(dpad),
None => Err(ParseError::Data {
frame,
detail: "There were bits that do not correspond to a flag. This means the `steering_wheel::Buttons` code is broken since every bit should have a flag.".to_owned(),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::{Buttons, Frame};
#[test]
fn stock_buttons_pressed() {
let all_buttons_pressed = Frame::from_id_data_len(
0x318,
[0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00],
8,
)
.unwrap();
let parsed = Buttons::try_from(all_buttons_pressed).unwrap();
assert_eq!(Buttons::all(), parsed);
assert_eq!(parsed.stock_buttons_pressed(), Buttons::STOCK_BUTTONS);
}
}