mod iter;
use sealed::Array;
pub(crate) use sealed::BitValueImpl;
use std::{ffi::c_ulong, fmt, slice};
mod sealed {
use super::Word;
pub trait BitValueImpl {
#[doc(hidden)]
type __PrivateArray: AsRef<[Word]>
+ AsMut<[Word]>
+ Copy
+ IntoIterator<Item = Word, IntoIter: Clone>;
#[doc(hidden)]
const __PRIVATE_ZERO: Self::__PrivateArray;
fn from_index(index: usize) -> Self;
fn into_index(self) -> usize;
}
pub(crate) type Array<V> = <V as BitValueImpl>::__PrivateArray;
}
pub type Word = c_ulong;
pub trait BitValue: Copy + sealed::BitValueImpl {
const MAX: Self;
}
pub struct BitSet<V: BitValue> {
pub(crate) words: Array<V>,
}
impl<V: BitValue> Copy for BitSet<V> {}
impl<V: BitValue> Clone for BitSet<V> {
fn clone(&self) -> Self {
*self
}
}
impl<V: BitValue> Default for BitSet<V> {
fn default() -> Self {
Self::new()
}
}
impl<V: BitValue> BitSet<V> {
pub const fn new() -> Self {
Self {
words: V::__PRIVATE_ZERO,
}
}
pub fn words(&self) -> &[Word] {
self.words.as_ref()
}
pub fn words_mut(&mut self) -> &mut [Word] {
self.words.as_mut()
}
pub fn len(&self) -> usize {
self.words
.as_ref()
.iter()
.map(|w| w.count_ones() as usize)
.sum::<usize>()
}
pub fn is_empty(&self) -> bool {
self.words.as_ref().iter().all(|&w| w == 0)
}
pub fn contains(&self, value: V) -> bool {
if value.into_index() > V::MAX.into_index() {
return false;
}
let index = value.into_index();
let wordpos = index / Word::BITS as usize;
let bitpos = index % Word::BITS as usize;
let word = self.words.as_ref()[wordpos];
let bit = word & (1 << bitpos) != 0;
bit
}
pub fn insert(&mut self, value: V) -> bool {
assert!(
value.into_index() <= V::MAX.into_index(),
"value out of range for `BitSet` storage (value's index is {}, max is {})",
value.into_index(),
V::MAX.into_index(),
);
let present = self.contains(value);
let index = value.into_index();
let wordpos = index / Word::BITS as usize;
let bitpos = index % Word::BITS as usize;
self.words.as_mut()[wordpos] |= 1 << bitpos;
present
}
pub fn remove(&mut self, value: V) -> bool {
if value.into_index() > V::MAX.into_index() {
return false;
}
let present = self.contains(value);
let index = value.into_index();
let wordpos = index / Word::BITS as usize;
let bitpos = index % Word::BITS as usize;
self.words.as_mut()[wordpos] &= !(1 << bitpos);
present
}
pub fn iter(&self) -> Iter<'_, V> {
Iter {
imp: iter::IterImpl::new(self.words.as_ref().iter().copied()),
}
}
pub(crate) fn symmetric_difference<'a>(
&'a self,
other: &'a BitSet<V>,
) -> SymmetricDifference<'a, V> {
SymmetricDifference {
imp: iter::IterImpl::new(SymmDiffWords {
a: self.words.as_ref().iter(),
b: other.words.as_ref().iter(),
}),
}
}
}
impl<V: BitValue + fmt::Debug> fmt::Debug for BitSet<V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
impl<V: BitValue> PartialEq for BitSet<V> {
fn eq(&self, other: &Self) -> bool {
self.words.as_ref() == other.words.as_ref()
}
}
impl<V: BitValue> Eq for BitSet<V> {}
impl<V: BitValue> FromIterator<V> for BitSet<V> {
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
let mut this = Self::new();
this.extend(iter);
this
}
}
impl<V: BitValue> Extend<V> for BitSet<V> {
fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
for item in iter {
self.insert(item);
}
}
}
impl<'a, V: BitValue> IntoIterator for &'a BitSet<V> {
type Item = V;
type IntoIter = Iter<'a, V>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<V: BitValue> IntoIterator for BitSet<V> {
type Item = V;
type IntoIter = IntoIter<V>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
imp: iter::IterImpl::new(self.words.into_iter()),
}
}
}
pub struct IntoIter<V: BitValue> {
imp: iter::IterImpl<V, <Array<V> as IntoIterator>::IntoIter>,
}
impl<V: BitValue> Iterator for IntoIter<V> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.imp.next()
}
}
impl<V: BitValue + fmt::Debug> fmt::Debug for IntoIter<V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("IntoIter")
.field(&DebugAsSet(self.imp.clone()))
.finish()
}
}
pub struct Iter<'a, V: BitValue> {
imp: iter::IterImpl<V, std::iter::Copied<slice::Iter<'a, Word>>>,
}
impl<V: BitValue> Iterator for Iter<'_, V> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.imp.next()
}
}
impl<V: BitValue + fmt::Debug> fmt::Debug for Iter<'_, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Iter")
.field(&DebugAsSet(self.imp.clone()))
.finish()
}
}
struct DebugAsSet<I>(I);
impl<I: Clone + Iterator> fmt::Debug for DebugAsSet<I>
where
I::Item: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.0.clone()).finish()
}
}
pub(crate) struct SymmetricDifference<'a, V: BitValue> {
imp: iter::IterImpl<V, SymmDiffWords<'a>>,
}
struct SymmDiffWords<'a> {
a: slice::Iter<'a, Word>,
b: slice::Iter<'a, Word>,
}
impl Iterator for SymmDiffWords<'_> {
type Item = Word;
fn next(&mut self) -> Option<Word> {
Some(self.a.next().copied()? ^ self.b.next().copied()?)
}
}
impl<V: BitValue> Iterator for SymmetricDifference<'_, V> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.imp.next()
}
}
#[cfg(test)]
mod tests {
use crate::{
InputProp,
event::{Abs, EventType, Key, Led, Misc, Rel},
};
use super::*;
#[test]
fn sizes() {
assert_eq!(size_of::<BitSet<EventType>>(), size_of::<Word>());
assert_eq!(size_of::<BitSet<InputProp>>(), size_of::<Word>());
assert_eq!(size_of::<BitSet<Rel>>(), size_of::<Word>());
assert_eq!(size_of::<BitSet<Misc>>(), size_of::<Word>());
assert_eq!(size_of::<BitSet<Led>>(), size_of::<Word>());
}
#[test]
fn bit0() {
let mut set = BitSet::new();
set.insert(InputProp(0));
assert!(set.contains(InputProp::POINTER));
assert!(!set.contains(InputProp::DIRECT));
assert!(!set.contains(InputProp::MAX));
assert!(!set.contains(InputProp(InputProp::MAX.0 + 1)));
assert!(!set.contains(InputProp(u8::MAX)));
assert_eq!(set.iter().collect::<Vec<_>>(), &[InputProp::POINTER]);
}
#[test]
fn max() {
let mut set = BitSet::new();
set.insert(InputProp::MAX);
assert!(!set.contains(InputProp::POINTER));
assert!(!set.contains(InputProp::DIRECT));
assert!(set.contains(InputProp::MAX));
assert!(!set.contains(InputProp(InputProp::MAX.0 + 1)));
assert!(!set.remove(InputProp(InputProp::MAX.0 + 1)));
}
#[test]
#[should_panic = "value out of range for `BitSet`"]
fn above_max() {
let mut set = BitSet::new();
set.insert(Abs::from_raw(Abs::MAX.raw() + 1));
}
#[test]
fn debug() {
let set = BitSet::from_iter([Abs::X, Abs::Y, Abs::BRAKE]);
assert_eq!(format!("{set:?}"), "{ABS_X, ABS_Y, ABS_BRAKE}");
let mut iter = set.iter();
assert_eq!(iter.next(), Some(Abs::X));
assert_eq!(format!("{iter:?}"), "Iter({ABS_Y, ABS_BRAKE})");
let mut iter = set.into_iter();
assert_eq!(iter.next(), Some(Abs::X));
assert_eq!(format!("{iter:?}"), "IntoIter({ABS_Y, ABS_BRAKE})");
}
#[test]
fn multiple() {
let mut set = BitSet::new();
set.insert(Key::KEY_RESERVED);
set.insert(Key::KEY_Q);
set.insert(Key::MAX);
set.insert(Key::KEY_MACRO1);
assert_eq!(
set.iter().collect::<Vec<_>>(),
&[Key::KEY_RESERVED, Key::KEY_Q, Key::KEY_MACRO1, Key::MAX]
);
}
#[test]
fn symmdiff() {
let mut a = BitSet::new();
a.insert(Key::KEY_B);
assert_eq!(
a.symmetric_difference(&BitSet::new()).collect::<Vec<_>>(),
&[Key::KEY_B]
);
assert_eq!(
BitSet::new().symmetric_difference(&a).collect::<Vec<_>>(),
&[Key::KEY_B]
);
let mut b = BitSet::new();
b.insert(Key::KEY_A);
assert_eq!(
a.symmetric_difference(&b).collect::<Vec<_>>(),
&[Key::KEY_A, Key::KEY_B]
);
assert_eq!(
b.symmetric_difference(&a).collect::<Vec<_>>(),
&[Key::KEY_A, Key::KEY_B]
);
assert_eq!(a.symmetric_difference(&a).collect::<Vec<_>>(), &[]);
assert_eq!(
BitSet::<Key>::new()
.symmetric_difference(&BitSet::new())
.collect::<Vec<_>>(),
&[]
);
}
}