use crate::types::Button;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LockTarget {
X,
Y,
Wheel,
Button(Button),
}
impl LockTarget {
pub fn as_u8(self) -> u8 {
match self {
LockTarget::X => 0,
LockTarget::Y => 1,
LockTarget::Wheel => 2,
LockTarget::Button(b) => 3 + b.as_id(),
}
}
pub fn from_u8(v: u8) -> Option<Self> {
Some(match v {
0 => LockTarget::X,
1 => LockTarget::Y,
2 => LockTarget::Wheel,
3..=7 => LockTarget::Button(Button::from_id(v - 3)?),
_ => return None,
})
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LockDirection {
Both = 0,
Positive = 1,
Negative = 2,
}
impl LockDirection {
pub fn as_u8(self) -> u8 {
self as u8
}
pub fn from_u8(v: u8) -> Option<Self> {
Some(match v {
0 => LockDirection::Both,
1 => LockDirection::Positive,
2 => LockDirection::Negative,
_ => return None,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Locks {
mask: u16,
}
impl Locks {
pub(crate) fn from_payload(p: &[u8]) -> Option<Self> {
if p.len() < 3 {
return None;
}
Some(Locks {
mask: u16::from_le_bytes([p[1], p[2]]),
})
}
pub fn mask(&self) -> u16 {
self.mask
}
pub fn is_locked(&self, target: LockTarget, dir: LockDirection) -> bool {
let base = target.as_u8() * 2;
let pos = self.mask & (1 << base) != 0;
let neg = self.mask & (1 << (base + 1)) != 0;
match dir {
LockDirection::Both => pos && neg,
LockDirection::Positive => pos,
LockDirection::Negative => neg,
}
}
}