use core::{fmt, str::FromStr};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
#[derive(
Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, FromPrimitive, ToPrimitive,
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum MouseCode {
#[default]
None = 0xff,
Mouse1 = 0x0,
Mouse2 = 0x1,
Mouse3 = 0x2,
Mouse4 = 0x3,
Mouse5 = 0x4,
Mouse6 = 0x5,
Mouse7 = 0x6,
Mouse8 = 0x7,
MouseWheelUp = 0x8,
MouseWheelDown = 0x9,
MouseMove = 0xa,
LeftMouseButton = 256,
RightMouseButton = 257,
MiddleWheelMouseButton = 258,
MouseButton3 = 259,
MouseButton4 = 260,
MouseButton5 = 261,
MouseButton6 = 262,
MouseButton7 = 263,
MouseWheelUp_ = 264,
MouseWheelDown_ = 265,
}
#[allow(non_camel_case_types)]
#[derive(
Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, FromPrimitive, ToPrimitive,
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum GamepadCode {
#[default]
None = 0xff,
Up = 0x0001,
Down = 0x0002,
Left = 0x0004,
Right = 0x008,
_360_Start = 0x0010,
_360_Back = 0x0020,
_360_L3 = 0x0040,
_360_R3 = 0x0080,
_360_LB = 0x0100,
_360_RB = 0x0200,
_360_A = 0x1000,
_360_B = 0x2000,
_360_X = 0x4000,
_360_Y = 0x8000,
_360_LT = 0x0009,
_360_RT = 0x000a,
_360_LS = 0x000b,
_360_RS = 0x000c,
DpadUp = 266,
DpadDown = 267,
DpadLeft = 268,
DpadRight = 269,
Start = 270,
Back = 271,
LeftThumb = 272,
RightThumb = 273,
LeftShoulder = 274,
RightShoulder = 275,
AButton = 276,
BButton = 277,
XButton = 278,
YButton = 279,
LeftTrigger = 280,
RightTrigger = 281,
}
#[allow(non_camel_case_types)]
#[derive(
Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash, FromPrimitive, ToPrimitive,
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum KeyboardCode {
#[default]
None = 0xff,
Esc = 0x01,
_1 = 0x02,
_2 = 0x03,
_3 = 0x04,
_4 = 0x05,
_5 = 0x06,
_6 = 0x07,
_7 = 0x08,
_8 = 0x09,
_9 = 0x0a,
_0 = 0x0b,
Hyphen = 0x0c,
Equal = 0x0d,
Backspace = 0x0e,
Tab = 0x0f,
Q = 0x10,
W = 0x11,
E = 0x12,
R = 0x13,
T = 0x14,
Y = 0x15,
U = 0x16,
I = 0x17,
O = 0x18,
P = 0x19,
Bracketleft = 0x1a,
Bracketright = 0x1b,
Enter = 0x1c,
LCtrl = 0x1d,
A = 0x1e,
S = 0x1f,
D = 0x20,
F = 0x21,
G = 0x22,
H = 0x23,
J = 0x24,
K = 0x25,
L = 0x26,
Semicolon = 0x27,
Quotesingle = 0x28,
Tilde = 0x29,
LShift = 0x2a,
Backslash = 0x2b,
Z = 0x2c,
X = 0x2d,
C = 0x2e,
V = 0x2f,
B = 0x30,
N = 0x31,
M = 0x32,
Comma = 0x33,
Period = 0x34,
Slash = 0x35,
RShift = 0x36,
NumpadMult = 0x37,
LAlt = 0x38,
Space = 0x39,
CapsLock = 0x3a,
F1 = 0x3b,
F2 = 0x3c,
F3 = 0x3d,
F4 = 0x3e,
F5 = 0x3f,
F6 = 0x40,
F7 = 0x41,
F8 = 0x42,
F9 = 0x43,
F10 = 0x44,
NumLock = 0x45,
ScrollLock = 0x46,
Numpad7 = 0x47,
Numpad8 = 0x48,
Numpad9 = 0x49,
NumpadMinus = 0x4a,
Numpad4 = 0x4b,
Numpad5 = 0x4c,
Numpad6 = 0x4d,
NumpadPlus = 0x4e,
Numpad1 = 0x4f,
Numpad2 = 0x50,
Numpad3 = 0x51,
Numpad0 = 0x52,
NumpadDec = 0x53,
DIK_OEM_102 = 0x56,
F11 = 0x57,
F12 = 0x58,
F13 = 0x64,
F14 = 0x65,
F15 = 0x66,
DIK_KANA = 0x70,
DIK_ABNT_C1 = 0x73,
DIK_CONVERT = 0x79,
DIK_NOCONVERT = 0x7b,
Unknown = 0x7d,
DIK_ABNT_C2 = 0x7e,
NumPadEqual = 0x8d,
PrevTrack = 0x90,
DIK_AT = 0x91,
Colon = 0x92,
DIK_UNDERLINE = 0x93,
DIK_KANJI = 0x94,
DIK_STOP = 0x95,
DIK_AX = 0x96,
DIK_UNLABELED = 0x97,
NextTrack = 0x99,
NumPadEnter = 0x9c,
RCtrl = 0x9d,
Mute = 0xa0,
Calc = 0xa1,
PlayPause = 0xa2,
MediaStop = 0xa4,
VolMinus = 0xae,
VolPlus = 0xb0,
WebHome = 0xb2,
NumpadComma = 0xb3,
NumpadDivide = 0xb5,
PrintSrc = 0xb7,
RAlt = 0xb8,
Pause = 0xc5,
Home = 0xc7,
UpArrow = 0xc8,
PgUp = 0xc9,
Left = 0xcb,
Right = 0xcd,
End = 0xcf,
DownArrow = 0xd0,
PgDn = 0xd1,
Insert = 0xd2,
Delete = 0xd3,
LWindows = 0xdb,
RWindows = 0xdc,
Apps = 0xdd,
Power = 0xde,
Sleep = 0xdf,
Wake = 0xe3,
WebSearch = 0xe5,
WebFavorites = 0xe6,
WebRefresh = 0xe7,
WebStop = 0xe8,
WebForward = 0xe9,
WebBack = 0xea,
MyComputer = 0xeb,
Mail = 0xec,
MediaSelect = 0xed,
}
trait ToRaw {
fn to_raw(&self) -> usize;
}
macro_rules! impl_cast {
($($self:ident),+ $(,)?) => {
$(
impl ToRaw for $self {
fn to_raw(&self) -> usize {
self.clone() as usize
}
}
impl TryFrom<usize> for $self {
type Error = ScanCodeError;
fn try_from(value: usize) -> Result<Self, Self::Error> {
FromPrimitive::from_usize(value)
.ok_or_else(|| ScanCodeError::InvalidDigit(format!("{}", value)))
}
}
impl FromStr for $self {
type Err = ScanCodeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let radix = match s.chars().next() {
Some('0') => {
match s.chars().nth(1) {
Some('x') | Some('X') => 16, Some('o') | Some('O') => 8, Some('b') | Some('B') => 2, _ => 10, }
}
_ => 10, };
let s = if radix != 10 { &s[2..] } else { s };
Self::try_from(
usize::from_str_radix(s, radix)
.map_err(|_| ScanCodeError::InvalidDigit(s.into()))?,
)
}
}
impl fmt::Display for $self {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{:x}", self.to_raw())
}
}
)+
};
}
impl_cast!(GamepadCode, KeyboardCode, MouseCode);
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ScanCodeError {
#[error("invalid digit found in string. got {0}")]
InvalidDigit(String),
}