#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Metas(u32);
impl Metas {
pub fn shift(&self) -> bool {
self.contains(Metas::SHIFT)
}
pub fn ctrl(&self) -> bool {
self.contains(Metas::CONTROL)
}
pub fn alt(&self) -> bool {
self.contains(Metas::ALT)
}
pub fn meta(&self) -> bool {
self.contains(Metas::META)
}
}
impl Metas {
pub const EMPTY: Self = Self::from_bits_retain(0);
pub const ALL: Self = Self::all();
pub const ALT: Self = Self::from_bits_retain(0x01);
pub const ALT_GRAPH: Self = Self::from_bits_retain(0x2);
pub const CAPS_LOCK: Self = Self::from_bits_retain(0x4);
pub const CONTROL: Self = Self::from_bits_retain(0x8);
pub const FN: Self = Self::from_bits_retain(0x10);
pub const FN_LOCK: Self = Self::from_bits_retain(0x20);
pub const META: Self = Self::from_bits_retain(0x40);
pub const NUM_LOCK: Self = Self::from_bits_retain(0x80);
pub const SCROLL_LOCK: Self = Self::from_bits_retain(0x100);
pub const SHIFT: Self = Self::from_bits_retain(0x200);
pub const SYMBOL: Self = Self::from_bits_retain(0x400);
pub const SYMBOL_LOCK: Self = Self::from_bits_retain(0x800);
pub const HYPER: Self = Self::from_bits_retain(0x1000);
pub const SUPER: Self = Self::from_bits_retain(0x2000);
}
impl Metas {
#[inline]
pub const fn is_empty(&self) -> bool {
self.0 == 0
}
#[inline]
pub const fn bits(&self) -> u32 {
self.0
}
#[inline]
pub const fn all() -> Self {
Self::from_bits_retain(
Self::ALT.0
| Self::ALT_GRAPH.0
| Self::CAPS_LOCK.0
| Self::CONTROL.0
| Self::FN.0 | Self::FN_LOCK.0
| Self::META.0 | Self::NUM_LOCK.0
| Self::SCROLL_LOCK.0
| Self::SHIFT.0 | Self::SYMBOL.0
| Self::SYMBOL_LOCK.0
| Self::HYPER.0 | Self::SUPER.0,
)
}
#[inline]
pub const fn from_bits_retain(bits: u32) -> Self {
Self(bits)
}
#[inline]
pub const fn from_bits_truncate(bits: u32) -> Self {
let bits = bits;
{
Self(bits & Self::all().bits())
}
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
let f = self;
let other = other;
{
f.bits() & other.bits() == other.bits()
}
}
#[inline]
pub fn insert(&mut self, other: Self) {
*self = Self::from_bits_retain(self.bits()).union(other);
}
#[inline]
pub fn remove(&mut self, other: Self) {
*self = Self::from_bits_retain(self.bits()).difference(other);
}
#[inline]
pub fn toggle(&mut self, other: Self) {
*self = Self::from_bits_retain(self.bits()).symmetric_difference(other);
}
#[inline]
pub fn set(&mut self, other: Self, value: bool) {
if value {
self.insert(other);
} else {
self.remove(other);
}
}
#[inline]
#[must_use]
pub const fn intersection(self, other: Self) -> Self {
Self::from_bits_retain(self.bits() & other.bits())
}
#[inline]
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self::from_bits_retain(self.bits() | other.bits())
}
#[inline]
#[must_use]
pub const fn difference(self, other: Self) -> Self {
Self::from_bits_retain(self.bits() & !other.bits())
}
#[inline]
#[must_use]
pub const fn symmetric_difference(self, other: Self) -> Self {
Self::from_bits_retain(self.bits() ^ other.bits())
}
#[inline]
#[must_use]
pub const fn complement(self) -> Self {
Self::from_bits_truncate(!self.bits())
}
#[inline]
pub fn from_name(name: &str) -> Option<Self> {
if name == "ALT" {
return Self::ALT.into();
}
if name == "ALT_GRAPH" {
return Self::ALT_GRAPH.into();
}
if name == "CAPS_LOCK" {
return Self::CAPS_LOCK.into();
}
if name == "CONTROL" {
return Self::CONTROL.into();
}
if name == "FN" {
return Self::FN.into();
}
if name == "FN_LOCK" {
return Self::FN_LOCK.into();
}
if name == "META" {
return Self::META.into();
}
if name == "NUM_LOCK" {
return Self::NUM_LOCK.into();
}
if name == "SCROLL_LOCK" {
return Self::SCROLL_LOCK.into();
}
if name == "SHIFT" {
return Self::SHIFT.into();
}
if name == "SYMBOL" {
return Self::SYMBOL.into();
}
if name == "SYMBOL_LOCK" {
return Self::SYMBOL_LOCK.into();
}
if name == "HYPER" {
return Self::HYPER.into();
}
if name == "SUPER" {
return Self::SUPER.into();
}
None
}
}
impl std::fmt::Debug for Metas {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut f = f.debug_tuple("");
if self.contains(Metas::ALT) {
f.field(&"ALT");
}
if self.contains(Metas::ALT_GRAPH) {
f.field(&"ALT_GRAPH");
}
if self.contains(Metas::CAPS_LOCK) {
f.field(&"CAPS_LOCK");
}
if self.contains(Metas::CONTROL) {
f.field(&"CONTROL");
}
if self.contains(Metas::FN) {
f.field(&"FN");
}
if self.contains(Metas::FN_LOCK) {
f.field(&"FN_LOCK");
}
if self.contains(Metas::META) {
f.field(&"META");
}
if self.contains(Metas::NUM_LOCK) {
f.field(&"NUM_LOCK");
}
if self.contains(Metas::SCROLL_LOCK) {
f.field(&"SCROLL_LOCK");
}
if self.contains(Metas::SHIFT) {
f.field(&"SHIFT");
}
if self.contains(Metas::SYMBOL) {
f.field(&"SYMBOL");
}
if self.contains(Metas::SYMBOL_LOCK) {
f.field(&"SYMBOL_LOCK");
}
if self.contains(Metas::HYPER) {
f.field(&"HYPER");
}
if self.contains(Metas::SUPER) {
f.field(&"SUPER");
}
f.finish()
}
}
impl core::ops::BitOr for Metas {
type Output = Self;
#[inline]
fn bitor(self, other: Metas) -> Self {
self.union(other)
}
}
impl core::ops::BitOrAssign for Metas {
#[inline]
fn bitor_assign(&mut self, other: Self) {
self.insert(other);
}
}
impl core::ops::BitXor for Metas {
type Output = Self;
#[inline]
fn bitxor(self, other: Self) -> Self {
self.symmetric_difference(other)
}
}
impl core::ops::BitXorAssign for Metas {
#[inline]
fn bitxor_assign(&mut self, other: Self) {
self.toggle(other);
}
}
impl core::ops::BitAnd for Metas {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
self.intersection(other)
}
}
impl core::ops::BitAndAssign for Metas {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self = Self::from_bits_retain(self.bits()).intersection(other);
}
}
impl core::ops::Sub for Metas {
type Output = Self;
#[inline]
fn sub(self, other: Self) -> Self {
self.difference(other)
}
}
impl core::ops::SubAssign for Metas {
#[inline]
fn sub_assign(&mut self, other: Self) {
self.remove(other);
}
}
impl core::ops::Not for Metas {
type Output = Self;
#[inline]
fn not(self) -> Self {
self.complement()
}
}