use std::{fmt, mem};
use crate::{event::Key, raw::input::input_keymap_entry};
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct KeymapEntry(pub(crate) input_keymap_entry);
impl KeymapEntry {
#[inline]
pub(crate) fn zeroed() -> Self {
unsafe { mem::zeroed() }
}
#[inline]
pub fn index(&self) -> u16 {
self.0.index
}
#[inline]
pub fn keycode(&self) -> Key {
let key = self.0.keycode as u16;
Key::from_raw(key)
}
#[inline]
pub fn scancode(&self) -> Scancode {
let len = self.0.len.min(32);
Scancode::from_ne_slice(&self.0.scancode[..len as usize])
}
}
impl fmt::Debug for KeymapEntry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("KeymapEntry")
.field("index", &self.index())
.field("keycode", &self.keycode())
.field("scancode", &self.scancode())
.finish()
}
}
#[derive(Clone, Copy)]
pub struct Scancode {
pub(crate) len: u8,
pub(crate) bytes: [u8; 32],
}
impl Scancode {
fn from_ne_slice(bytes: &[u8]) -> Self {
assert!(bytes.len() <= 32);
let mut a = [0; 32];
a[..bytes.len()].copy_from_slice(&bytes);
Self {
len: bytes.len() as u8,
bytes: a,
}
}
fn as_ne_bytes(&self) -> &[u8] {
&self.bytes[..self.len as usize]
}
fn iter_ne_bytes(&self) -> impl DoubleEndedIterator<Item = u8> {
self.as_ne_bytes().iter().copied()
}
fn iter_be_bytes(&self) -> impl Iterator<Item = u8> {
#[cfg(target_endian = "little")]
return self.iter_ne_bytes().rev();
#[cfg(target_endian = "big")]
return self.iter_ne_bytes();
}
}
impl From<u8> for Scancode {
#[inline]
fn from(value: u8) -> Self {
Self::from_ne_slice(&[value])
}
}
impl From<u16> for Scancode {
#[inline]
fn from(value: u16) -> Self {
Self::from_ne_slice(&value.to_ne_bytes())
}
}
impl From<u32> for Scancode {
#[inline]
fn from(value: u32) -> Self {
Self::from_ne_slice(&value.to_ne_bytes())
}
}
impl fmt::Debug for Scancode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut any_nonzero = false;
for (i, byte) in self.iter_be_bytes().skip_while(|b| *b == 0).enumerate() {
if i == 0 {
write!(f, "{byte:x}")?;
} else {
write!(f, "{byte:02x}")?;
}
any_nonzero = true;
}
if !any_nonzero {
f.write_str("0")?;
}
Ok(())
}
}
impl fmt::Display for Scancode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Debug>::fmt(self, f)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn smoke() {
let code = Scancode::from(0u8);
assert_eq!(format!("{code}"), "0");
let code = Scancode::from(1u8);
assert_eq!(format!("{code}"), "1");
let code = Scancode::from(10u8);
assert_eq!(format!("{code}"), "a");
let code = Scancode::from(0x10u8);
assert_eq!(format!("{code}"), "10");
let code = Scancode::from(0x100u16);
assert_eq!(format!("{code}"), "100");
let code = Scancode::from(0x1000u16);
assert_eq!(format!("{code}"), "1000");
}
}