diff --git a/src/key/keystate.rs b/src/key/keystate.rs index d652fe5..5d1a7ea 100644 --- a/src/key/keystate.rs +++ b/src/key/keystate.rs @@ -2,7 +2,7 @@ use std::ffi::OsString; use winapi::um::winuser::{GetKeyNameTextW, KBDLLHOOKSTRUCT, LLKHF_EXTENDED, LLKHF_UP}; use wio::wide::FromWide; -use crate::get_flag; +use crate::FlagOperations; #[allow(clippy::struct_excessive_bools)] pub struct KeyState { @@ -33,7 +33,7 @@ impl KeyState { /// `key_down` if the event was a keydown event, this should be true. if it was keyup it should be false pub fn update(&mut self, key: KBDLLHOOKSTRUCT) { - let key_down = !get_flag(key.flags, LLKHF_UP); + let key_down = !key.flags.get_flag(LLKHF_UP); self.kbdllstruct = key; match key.vkCode { @@ -53,7 +53,7 @@ impl KeyState { #[no_mangle] //required to not get garbage from native call pub fn name(&self) -> String { unsafe { - let flags = if get_flag(self.kbdllstruct.flags, LLKHF_EXTENDED) { 1 << 24 } else { 0 }; + let flags = if self.kbdllstruct.flags.get_flag(LLKHF_EXTENDED) { 1 << 24 } else { 0 }; let mut out = [0_u16; 128]; GetKeyNameTextW((self.kbdllstruct.scanCode << 16 | flags /*this distinguishes special keys by setting a flag. yes only microsoft thinks that input and flags in 1 param is a good idea*/) as i32, (&mut out).as_mut_ptr(), 128); @@ -64,7 +64,7 @@ impl KeyState { ///true if this event is keydown, otherwise false pub fn is_down(&self) -> bool { - !get_flag(self.kbdllstruct.flags, LLKHF_UP) + !self.kbdllstruct.flags.get_flag(LLKHF_UP) } } diff --git a/src/lib.rs b/src/lib.rs index a111f3c..2cd5bda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,38 +12,49 @@ clippy::cast_lossless, clippy::cast_possible_wrap, //lossy casts are required to pub mod logging; pub mod key; -///gets the flag at the position of `flag`. `flag` must have exactly 1 bit set -fn get_flag(val: u32, flag: u32) -> bool { - if has_one_bit_set(flag) { - val & flag != 0 - } else { - panic!("flag must have 1 bit set") +//TODO generify this? +impl FlagOperations for u32 { + fn has_one_bit_set(&self) -> bool { + *self > 0 && *self & (*self - 1) == 0 + } + + fn get_flag(&self, flag: Self) -> bool { + if flag.has_one_bit_set() { + self & flag != 0 + } else { + panic!("flag must have 1 bit set") + } } } -///true if exactly 1 bit of the given number is set -fn has_one_bit_set(n: u32) -> bool { - //Dont ask me why this works! its mathgic! - n > 0 && n & (n - 1) == 0 +trait FlagOperations { + ///true if exactly 1 bit of the given number is set + fn has_one_bit_set(&self) -> bool; + + ///gets the flag at the position of `flag`. `flag` must have exactly 1 bit set + /// `flag` should have 1 bit set at the position of the flag to get + fn get_flag(&self, flag: Self) -> bool; } #[cfg(test)] mod tests { + use crate::FlagOperations; + #[test] fn get_flag() { - assert!(super::get_flag(5, 1 << 2)); - assert!(!super::get_flag(3, 1 << 2)); + assert!(5u32.get_flag(1 << 2)); + assert!(!3u32.get_flag(1 << 2)); } #[test] #[should_panic] fn get_flag_panic() { - super::get_flag(0, 3); + 0u32.get_flag(3); } #[test] fn has_one_bit_set() { - assert!(super::has_one_bit_set(1)); - assert!(!super::has_one_bit_set(3)); + assert!(1u32.has_one_bit_set()); + assert!(!3u32.has_one_bit_set()); } }