#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(u32)]
pub enum PointerButton {
Primary = 1,
Secondary = 1 << 1,
Auxiliary = 1 << 2,
X1 = 1 << 3,
X2 = 1 << 4,
PenEraser = 1 << 5,
B7 = 1 << 6,
B8 = 1 << 7,
B9 = 1 << 8,
B10 = 1 << 9,
B11 = 1 << 10,
B12 = 1 << 11,
B13 = 1 << 12,
B14 = 1 << 13,
B15 = 1 << 14,
B16 = 1 << 15,
B17 = 1 << 16,
B18 = 1 << 17,
B19 = 1 << 18,
B20 = 1 << 19,
B21 = 1 << 20,
B22 = 1 << 21,
B23 = 1 << 22,
B24 = 1 << 23,
B25 = 1 << 24,
B26 = 1 << 25,
B27 = 1 << 26,
B28 = 1 << 27,
B29 = 1 << 28,
B30 = 1 << 29,
B31 = 1 << 30,
B32 = 1 << 31,
}
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct PointerButtons(u32);
impl PointerButtons {
#[inline]
pub fn new() -> Self {
Self(0)
}
#[inline]
pub fn insert(&mut self, button: PointerButton) {
self.0 |= button as u32;
}
#[inline]
pub fn remove(&mut self, button: PointerButton) {
self.0 &= !(button as u32);
}
#[inline]
pub fn contains(self, button: PointerButton) -> bool {
(self.0 & button as u32) != 0
}
#[inline]
pub fn is_empty(self) -> bool {
self.0 == 0
}
#[inline]
pub fn contains_all(self, buttons: Self) -> bool {
self.0 & buttons.0 == buttons.0
}
#[inline]
pub fn extend(&mut self, buttons: Self) {
self.0 |= buttons.0;
}
#[inline]
pub fn clear(&mut self) {
self.0 = 0;
}
#[inline]
pub fn count(self) -> u32 {
self.0.count_ones()
}
}
const NONZERO_VARIANTS: [PointerButton; 32] = [
PointerButton::Primary,
PointerButton::Secondary,
PointerButton::Auxiliary,
PointerButton::X1,
PointerButton::X2,
PointerButton::PenEraser,
PointerButton::B7,
PointerButton::B8,
PointerButton::B9,
PointerButton::B10,
PointerButton::B11,
PointerButton::B12,
PointerButton::B13,
PointerButton::B14,
PointerButton::B15,
PointerButton::B16,
PointerButton::B17,
PointerButton::B18,
PointerButton::B19,
PointerButton::B20,
PointerButton::B21,
PointerButton::B22,
PointerButton::B23,
PointerButton::B24,
PointerButton::B25,
PointerButton::B26,
PointerButton::B27,
PointerButton::B28,
PointerButton::B29,
PointerButton::B30,
PointerButton::B31,
PointerButton::B32,
];
impl core::fmt::Debug for PointerButtons {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_empty() {
return f.write_str("PointerButtons(None)");
}
f.write_str("PointerButtons(")?;
if f.alternate() && self.count() > 2 {
f.write_str("\n ")?;
}
let mut first = true;
for button in NONZERO_VARIANTS {
if self.contains(button) {
if !first {
if f.alternate() && self.count() > 2 {
f.write_str("\n | ")?;
} else {
f.write_str(" | ")?;
}
}
first = false;
button.fmt(f)?;
}
}
if f.alternate() && self.count() > 2 {
f.write_str("\n)")
} else {
f.write_str(")")
}
}
}
impl core::fmt::Binary for PointerButtons {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Binary::fmt(&self.0, f)
}
}
impl core::ops::BitOr for PointerButton {
type Output = PointerButtons;
fn bitor(self, rhs: Self) -> Self::Output {
PointerButtons(self as u32 | rhs as u32)
}
}
impl core::ops::BitOr<PointerButton> for PointerButtons {
type Output = Self;
fn bitor(self, rhs: PointerButton) -> Self {
Self(self.0 | rhs as u32)
}
}
impl core::ops::BitOrAssign<PointerButton> for PointerButtons {
fn bitor_assign(&mut self, rhs: PointerButton) {
self.0 |= rhs as u32;
}
}
impl From<PointerButton> for PointerButtons {
fn from(button: PointerButton) -> Self {
Self(button as u32)
}
}
#[cfg(test)]
mod tests {
#[test]
fn debug_fmt() {
use crate::pointer::{PointerButton, PointerButtons};
extern crate std;
use std::format;
assert_eq!(
format!("{:?}", PointerButtons::default()),
"PointerButtons(None)"
);
assert_eq!(
format!("{:?}", PointerButtons::from(PointerButton::Primary)),
"PointerButtons(Primary)"
);
assert_eq!(
format!("{:?}", PointerButton::Primary | PointerButton::Auxiliary),
"PointerButtons(Primary | Auxiliary)"
);
assert_eq!(
format!(
"{:?}",
PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary
),
"PointerButtons(Primary | Secondary | Auxiliary)"
);
assert_eq!(
format!(
"{:#?}",
(
PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary,
PointerButton::B7 | PointerButton::X2
)
),
"(
PointerButtons(
Primary
| Secondary
| Auxiliary
),
PointerButtons(X2 | B7),
)"
);
assert_eq!(
format!("{:?}", PointerButton::B32 | PointerButton::Primary),
"PointerButtons(Primary | B32)"
);
}
#[test]
fn option_niche_opt() {
use crate::pointer::PointerButton;
use core::mem::size_of;
assert_eq!(
size_of::<Option<PointerButton>>(),
size_of::<PointerButton>()
);
}
}