use crate::protocol::opcode::{CATCH_ALL, CATCH_BUTTONS, CATCH_MASK, CATCH_MOTION, CATCH_WHEEL};
use crate::types::Button;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct CatchMask(u8);
impl CatchMask {
pub const MOTION: CatchMask = CatchMask(CATCH_MOTION);
pub const WHEEL: CatchMask = CatchMask(CATCH_WHEEL);
pub const BUTTONS: CatchMask = CatchMask(CATCH_BUTTONS);
pub const fn empty() -> CatchMask {
CatchMask(0)
}
pub const fn all() -> CatchMask {
CatchMask(CATCH_ALL)
}
pub const fn from_bits_truncate(bits: u8) -> CatchMask {
CatchMask(bits & CATCH_MASK)
}
pub const fn bits(self) -> u8 {
self.0
}
pub const fn is_empty(self) -> bool {
self.0 == 0
}
pub const fn contains(self, other: CatchMask) -> bool {
self.0 & other.0 == other.0
}
pub const fn union(self, other: CatchMask) -> CatchMask {
CatchMask(self.0 | other.0)
}
}
impl core::ops::BitOr for CatchMask {
type Output = CatchMask;
fn bitor(self, rhs: CatchMask) -> CatchMask {
self.union(rhs)
}
}
impl core::ops::BitOrAssign for CatchMask {
fn bitor_assign(&mut self, rhs: CatchMask) {
self.0 |= rhs.0;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InputReport {
pub buttons: u8,
pub dx: i16,
pub dy: i16,
pub wheel: i16,
}
impl InputReport {
pub(crate) fn from_payload(p: &[u8]) -> Option<InputReport> {
if p.len() < 7 {
return None;
}
Some(InputReport {
buttons: p[0],
dx: i16::from_le_bytes([p[1], p[2]]),
dy: i16::from_le_bytes([p[3], p[4]]),
wheel: i16::from_le_bytes([p[5], p[6]]),
})
}
pub fn is_pressed(self, button: Button) -> bool {
self.buttons & (1 << button.as_id()) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CatchState {
pub mask: CatchMask,
pub dropped: u32,
}
impl CatchState {
pub(crate) fn from_payload(p: &[u8]) -> Option<CatchState> {
if p.len() < 6 {
return None;
}
Some(CatchState {
mask: CatchMask::from_bits_truncate(p[1]),
dropped: u32::from_le_bytes([p[2], p[3], p[4], p[5]]),
})
}
}