2021-02-25 01:09:44 +00:00
|
|
|
use bitvec::prelude::*;
|
|
|
|
use std::fmt;
|
2021-03-17 02:38:42 +00:00
|
|
|
use std::ops::{Deref, DerefMut};
|
2021-02-25 01:09:44 +00:00
|
|
|
|
2021-03-01 21:27:03 +00:00
|
|
|
/// A collection of bits representing either device capability or state.
|
|
|
|
///
|
|
|
|
/// This can be used to iterate across all keys supported by a keyboard, or all buttons supported
|
|
|
|
/// by a joystick. You can also query directly whether a specific bit is set (corresponding to
|
|
|
|
/// whether a key or button is depressed).
|
2021-03-17 02:38:42 +00:00
|
|
|
#[repr(transparent)]
|
|
|
|
pub struct AttributeSetRef<T> {
|
2021-02-25 01:09:44 +00:00
|
|
|
_indexer: std::marker::PhantomData<T>,
|
2021-12-01 19:03:51 +00:00
|
|
|
bitslice: BitSlice<u8>,
|
2021-02-25 01:09:44 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 02:38:42 +00:00
|
|
|
impl<T: EvdevEnum> AttributeSetRef<T> {
|
2021-02-25 01:09:44 +00:00
|
|
|
#[inline]
|
2021-12-01 19:03:51 +00:00
|
|
|
fn new(bitslice: &BitSlice<u8>) -> &Self {
|
|
|
|
// SAFETY: for<T> AttributeSet<T> is repr(transparent) over BitSlice<u8>
|
|
|
|
unsafe { &*(bitslice as *const BitSlice<u8> as *const Self) }
|
2021-02-25 01:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2021-12-01 19:03:51 +00:00
|
|
|
fn new_mut(bitslice: &mut BitSlice<u8>) -> &mut Self {
|
|
|
|
// SAFETY: for<T> AttributeSet<T> is repr(transparent) over BitSlice<u8>
|
|
|
|
unsafe { &mut *(bitslice as *mut BitSlice<u8> as *mut Self) }
|
2021-03-17 02:38:42 +00:00
|
|
|
}
|
|
|
|
|
2021-03-01 21:27:03 +00:00
|
|
|
/// Returns `true` if this AttributeSet contains the passed T.
|
2021-03-17 02:38:42 +00:00
|
|
|
#[inline]
|
2021-02-25 01:09:44 +00:00
|
|
|
pub fn contains(&self, attr: T) -> bool {
|
|
|
|
self.bitslice.get(attr.to_index()).map_or(false, |b| *b)
|
|
|
|
}
|
|
|
|
|
2021-03-01 21:27:03 +00:00
|
|
|
/// Provides an iterator over all "set" bits in the collection.
|
2021-03-17 02:38:42 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
|
2021-02-25 01:09:44 +00:00
|
|
|
self.bitslice.iter_ones().map(T::from_index)
|
|
|
|
}
|
2021-03-17 02:38:42 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn slice(&self, start: T) -> &Self {
|
|
|
|
Self::new(&self.bitslice[start.to_index()..])
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn insert(&mut self, attr: T) {
|
|
|
|
self.set(attr, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn remove(&mut self, attr: T) {
|
|
|
|
self.set(attr, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: figure out a good name for this if we make it public
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn set(&mut self, attr: T, on: bool) {
|
|
|
|
self.bitslice.set(attr.to_index(), on)
|
|
|
|
}
|
2021-02-25 01:09:44 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 02:38:42 +00:00
|
|
|
impl<T: EvdevEnum + fmt::Debug> fmt::Debug for AttributeSetRef<T> {
|
2021-02-25 01:09:44 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
f.debug_set().entries(self.iter()).finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-17 02:38:42 +00:00
|
|
|
pub struct AttributeSet<T: ArrayedEvdevEnum> {
|
|
|
|
container: T::Array,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ArrayedEvdevEnum> AttributeSet<T> {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
container: T::zeroed_array(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-01 19:03:51 +00:00
|
|
|
fn as_bitslice(&self) -> &BitSlice<u8> {
|
2021-03-17 02:38:42 +00:00
|
|
|
T::array_as_slice(&self.container)
|
|
|
|
}
|
|
|
|
|
2021-12-01 19:03:51 +00:00
|
|
|
fn as_mut_bitslice(&mut self) -> &mut BitSlice<u8> {
|
2021-03-17 02:38:42 +00:00
|
|
|
T::array_as_slice_mut(&mut self.container)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn as_mut_raw_slice(&mut self) -> &mut [u8] {
|
|
|
|
T::array_as_buf(&mut self.container)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ArrayedEvdevEnum> Default for AttributeSet<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ArrayedEvdevEnum> Deref for AttributeSet<T> {
|
|
|
|
type Target = AttributeSetRef<T>;
|
|
|
|
fn deref(&self) -> &AttributeSetRef<T> {
|
|
|
|
AttributeSetRef::new(self.as_bitslice())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ArrayedEvdevEnum> DerefMut for AttributeSet<T> {
|
|
|
|
fn deref_mut(&mut self) -> &mut AttributeSetRef<T> {
|
|
|
|
AttributeSetRef::new_mut(self.as_mut_bitslice())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ArrayedEvdevEnum> Clone for AttributeSet<T>
|
|
|
|
where
|
|
|
|
T::Array: Clone,
|
|
|
|
{
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
container: self.container.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn clone_from(&mut self, other: &Self) {
|
|
|
|
self.container.clone_from(&other.container)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: ArrayedEvdevEnum + fmt::Debug> fmt::Debug for AttributeSet<T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
(**self).fmt(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-25 01:09:44 +00:00
|
|
|
pub trait EvdevEnum: Copy + 'static {
|
|
|
|
fn from_index(i: usize) -> Self;
|
|
|
|
fn to_index(self) -> usize;
|
|
|
|
}
|
|
|
|
|
2021-03-17 02:38:42 +00:00
|
|
|
pub trait ArrayedEvdevEnum: EvdevEnum {
|
|
|
|
type Array;
|
2021-12-01 19:03:51 +00:00
|
|
|
fn array_as_slice(arr: &Self::Array) -> &BitSlice<u8>;
|
|
|
|
fn array_as_slice_mut(arr: &mut Self::Array) -> &mut BitSlice<u8>;
|
2021-03-17 02:38:42 +00:00
|
|
|
fn array_as_buf(arr: &mut Self::Array) -> &mut [u8];
|
|
|
|
fn zeroed_array() -> Self::Array;
|
|
|
|
}
|
|
|
|
|
2021-02-25 01:09:44 +00:00
|
|
|
macro_rules! evdev_enum {
|
2021-03-17 02:38:42 +00:00
|
|
|
($t:ty, Array, $($(#[$attr:meta])* $c:ident = $val:expr,)*) => {
|
|
|
|
evdev_enum!(
|
|
|
|
$t,
|
2021-12-01 19:57:59 +00:00
|
|
|
Array: bitvec::BitArr!(for <$t>::COUNT, in u8),
|
2021-12-01 19:03:51 +00:00
|
|
|
bitvec::array::BitArray::as_raw_mut_slice,
|
|
|
|
bitvec::array::BitArray::ZERO,
|
2021-12-01 18:57:11 +00:00
|
|
|
$($(#[$attr])* $c = $val,)*
|
|
|
|
);
|
|
|
|
};
|
|
|
|
($t:ty, box Array, $($(#[$attr:meta])* $c:ident = $val:expr,)*) => {
|
|
|
|
evdev_enum!(
|
|
|
|
$t,
|
2021-12-01 19:57:59 +00:00
|
|
|
Array: Box<bitvec::BitArr!(for <$t>::COUNT, in u8)>,
|
2021-12-01 19:03:51 +00:00
|
|
|
bitvec::array::BitArray::as_raw_mut_slice,
|
|
|
|
Box::new(bitvec::array::BitArray::ZERO),
|
2021-03-17 02:38:42 +00:00
|
|
|
$($(#[$attr])* $c = $val,)*
|
|
|
|
);
|
|
|
|
};
|
|
|
|
(
|
|
|
|
$t:ty,
|
2021-12-01 18:57:11 +00:00
|
|
|
Array: $Array:ty, $arr_as_buf:expr, $zero:expr,
|
2021-03-17 02:38:42 +00:00
|
|
|
$($(#[$attr:meta])* $c:ident = $val:expr,)*
|
|
|
|
) => {
|
|
|
|
impl $crate::attribute_set::ArrayedEvdevEnum for $t {
|
|
|
|
type Array = $Array;
|
2021-12-01 19:03:51 +00:00
|
|
|
fn array_as_slice(arr: &Self::Array) -> &bitvec::slice::BitSlice<u8> {
|
2021-12-01 18:57:11 +00:00
|
|
|
arr
|
2021-03-17 02:38:42 +00:00
|
|
|
}
|
2021-12-01 19:03:51 +00:00
|
|
|
fn array_as_slice_mut(arr: &mut Self::Array) -> &mut bitvec::slice::BitSlice<u8> {
|
2021-12-01 18:57:11 +00:00
|
|
|
arr
|
2021-03-17 02:38:42 +00:00
|
|
|
}
|
|
|
|
fn array_as_buf(arr: &mut Self::Array) -> &mut [u8] {
|
2021-12-01 18:57:11 +00:00
|
|
|
$arr_as_buf(arr)
|
2021-03-17 02:38:42 +00:00
|
|
|
}
|
|
|
|
fn zeroed_array() -> Self::Array {
|
2021-12-01 18:57:11 +00:00
|
|
|
$zero
|
2021-03-17 02:38:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
evdev_enum!($t, $($(#[$attr])* $c = $val,)*);
|
|
|
|
};
|
2021-02-25 01:09:44 +00:00
|
|
|
($t:ty, $($(#[$attr:meta])* $c:ident = $val:expr,)*) => {
|
|
|
|
impl $t {
|
|
|
|
$($(#[$attr])* pub const $c: Self = Self($val);)*
|
|
|
|
}
|
2021-06-27 09:04:44 +00:00
|
|
|
impl std::str::FromStr for $t {
|
|
|
|
type Err = crate::EnumParseError;
|
|
|
|
|
2021-12-01 19:57:59 +00:00
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
2021-06-27 09:04:44 +00:00
|
|
|
let map: &[(&'static str, $t)] = &[
|
|
|
|
$((stringify!($c), Self::$c),)*
|
|
|
|
];
|
|
|
|
|
|
|
|
match map.iter().find(|e| e.0 == s) {
|
|
|
|
Some(e) => Ok(e.1),
|
|
|
|
None => Err(crate::EnumParseError(())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-25 01:09:44 +00:00
|
|
|
impl std::fmt::Debug for $t {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
2021-07-20 16:40:49 +00:00
|
|
|
#[allow(unreachable_patterns)]
|
2021-02-25 01:09:44 +00:00
|
|
|
match *self {
|
|
|
|
$(Self::$c => f.pad(stringify!($c)),)*
|
|
|
|
_ => write!(f, "unknown key: {}", self.0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl $crate::attribute_set::EvdevEnum for $t {
|
|
|
|
#[inline]
|
|
|
|
fn from_index(i: usize) -> Self {
|
|
|
|
Self(i as _)
|
|
|
|
}
|
|
|
|
#[inline]
|
|
|
|
fn to_index(self) -> usize {
|
|
|
|
self.0 as _
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|