Skip to content

Commit 47c4881

Browse files
authored
Merge pull request #160 from hpccc53/main
2 parents 5d282a0 + 66deafe commit 47c4881

File tree

6 files changed

+256
-8
lines changed

6 files changed

+256
-8
lines changed

src/attribute_set.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ impl<T: EvdevEnum> AttributeSetRef<T> {
3838
self.into_iter()
3939
}
4040

41-
#[inline]
42-
pub(crate) fn slice(&self, start: T) -> &Self {
43-
Self::new(&self.bitslice[start.to_index()..])
44-
}
45-
4641
pub fn insert(&mut self, attr: T) {
4742
self.set(attr, true)
4843
}
@@ -56,6 +51,17 @@ impl<T: EvdevEnum> AttributeSetRef<T> {
5651
pub(crate) fn set(&mut self, attr: T, on: bool) {
5752
self.bitslice.set(attr.to_index(), on)
5853
}
54+
55+
#[inline]
56+
pub(crate) fn slice_iter(&self, start: T) -> AttributeSetRefIter<T> {
57+
let slice = Self::new(&self.bitslice[start.to_index()..]);
58+
59+
AttributeSetRefIter {
60+
_indexer: std::marker::PhantomData,
61+
inner: slice.bitslice.iter_ones(),
62+
offset: start.to_index(),
63+
}
64+
}
5965
}
6066

6167
impl<T: EvdevEnum + fmt::Debug> fmt::Debug for AttributeSetRef<T> {
@@ -83,20 +89,24 @@ impl<'a, T: EvdevEnum> IntoIterator for &'a AttributeSetRef<T> {
8389
AttributeSetRefIter {
8490
_indexer: std::marker::PhantomData,
8591
inner: self.bitslice.iter_ones(),
92+
offset: 0,
8693
}
8794
}
8895
}
8996

9097
pub struct AttributeSetRefIter<'a, T> {
9198
_indexer: std::marker::PhantomData<&'a T>,
9299
inner: bitvec::slice::IterOnes<'a, u8, Lsb0>,
100+
offset: usize,
93101
}
94102

95103
impl<T: EvdevEnum> Iterator for AttributeSetRefIter<'_, T> {
96104
type Item = T;
97105

98106
fn next(&mut self) -> Option<Self::Item> {
99-
self.inner.next().map(T::from_index)
107+
self.inner
108+
.next()
109+
.map(|idx| T::from_index(self.offset + idx))
100110
}
101111
}
102112

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ pub mod raw_stream;
175175
mod scancodes;
176176
mod sync_stream;
177177
mod sys;
178+
#[cfg(test)]
179+
mod tests;
178180
pub mod uinput;
179181

180182
use crate::compat::{input_absinfo, input_event, uinput_abs_setup};

src/sync_stream.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,12 @@ fn compensate_events(state: &mut Option<SyncState>, dev: &mut Device) -> Option<
485485
macro_rules! try_compensate {
486486
($time:expr, $start:ident : $typ:ident, $evtype:ident, $sync:ident, $supporteds:ident, $state:ty, $get_state:expr, $get_value:expr) => {
487487
if let Some(supported_types) = dev.$supporteds() {
488-
let types_to_check = supported_types.slice(*$start);
488+
let types_to_check = supported_types.slice_iter(*$start);
489489
let get_state: fn(&DeviceState) -> $state = $get_state;
490490
let vals = get_state(&dev.state);
491491
let old_vals = get_state(&dev.prev_state);
492492
let get_value: fn($state, $typ) -> _ = $get_value;
493-
for typ in types_to_check.iter() {
493+
for typ in types_to_check {
494494
let prev = get_value(old_vals, typ);
495495
let value = get_value(vals, typ);
496496
if prev != value {
@@ -889,6 +889,7 @@ pub use tokio_stream::EventStream;
889889
#[cfg(test)]
890890
mod tests {
891891
use super::*;
892+
use crate::tests::{get_test_device, key_event};
892893

893894
fn result_events_iter(
894895
events: &[input_event],
@@ -956,4 +957,23 @@ mod tests {
956957
assert_eq!(next(), (Err(false), None));
957958
assert_eq!(next(), (Err(false), None));
958959
}
960+
961+
#[test]
962+
pub fn test_get_key_state() -> Result<(), Box<dyn std::error::Error>> {
963+
let (input, mut output) = get_test_device()?;
964+
965+
output.emit(&[key_event(KeyCode::KEY_DOT, 1)])?;
966+
967+
assert_eq!(1, input.get_key_state()?.iter().count());
968+
assert!(input
969+
.get_key_state()?
970+
.iter()
971+
.all(|e| e.code() == KeyCode::KEY_DOT.code()));
972+
973+
output.emit(&[key_event(KeyCode::KEY_DOT, 0)])?;
974+
975+
assert_eq!(0, input.get_key_state()?.iter().count());
976+
977+
Ok(())
978+
}
959979
}

src/tests/attribute_set.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use crate::tests::get_test_device;
2+
use crate::{AttributeSet, KeyCode};
3+
4+
#[test]
5+
pub fn test_iteration_keys() -> std::io::Result<()> {
6+
let (input, _) = get_test_device()?;
7+
8+
let keys = input.supported_keys().unwrap();
9+
10+
assert_eq!(58, keys.iter().count());
11+
12+
let mut expected: i16 = 58;
13+
14+
for typ in keys.iter() {
15+
expected -= 1;
16+
17+
assert_eq!(
18+
expected as usize,
19+
keys.slice_iter(KeyCode(typ.0 + 1)).count()
20+
);
21+
}
22+
23+
Ok(())
24+
}
25+
26+
#[test]
27+
pub fn test_first_element_in_slice_iter() -> std::io::Result<()> {
28+
let mut keys: AttributeSet<KeyCode> = AttributeSet::new();
29+
keys.insert(KeyCode(0));
30+
keys.insert(KeyCode(1));
31+
32+
assert_eq!(KeyCode(0), keys.slice_iter(KeyCode(0)).nth(0).unwrap());
33+
assert_eq!(KeyCode(1), keys.slice_iter(KeyCode(1)).nth(0).unwrap());
34+
35+
Ok(())
36+
}

src/tests/compensate.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use crate::tests::{final_dot_state, final_event_state, get_test_device, key_click, key_event};
2+
use crate::{EventType, InputEvent, KeyCode, SwitchCode};
3+
4+
#[test]
5+
pub fn test_compensate_keys() -> std::io::Result<()> {
6+
let (mut input, mut output) = get_test_device()?;
7+
8+
let dot_state: i32 = 0;
9+
10+
// Make overflow.
11+
for _ in 0..30 {
12+
output.emit(&key_click(KeyCode::KEY_DOT))?;
13+
}
14+
15+
let dot_state = final_dot_state(dot_state, input.fetch_events()?);
16+
17+
assert_eq!(0, dot_state);
18+
19+
// Press and release.
20+
output.emit(&key_click(KeyCode::KEY_DOT))?;
21+
22+
let dot_state = final_dot_state(dot_state, input.fetch_events()?);
23+
24+
assert_eq!(0, dot_state);
25+
26+
// Just press.
27+
output.emit(&[key_event(KeyCode::KEY_DOT, 1)])?;
28+
29+
let dot_state = final_dot_state(dot_state, input.fetch_events()?);
30+
31+
assert_eq!(1, dot_state);
32+
33+
Ok(())
34+
}
35+
36+
#[test]
37+
pub fn test_compensate_with_key_down() -> std::io::Result<()> {
38+
let (mut input, mut output) = get_test_device()?;
39+
40+
output.emit(&[InputEvent::new(EventType::KEY.0, KeyCode::KEY_A.0, 1)])?;
41+
output.emit(&[InputEvent::new(EventType::KEY.0, KeyCode::KEY_B.0, 1)])?;
42+
43+
// Make overflow.
44+
for _ in 0..30 {
45+
output.emit(&key_click(KeyCode::KEY_DOT))?;
46+
}
47+
48+
assert_eq!(0, input.fetch_events()?.into_iter().count());
49+
50+
// Press and release.
51+
output.emit(&key_click(KeyCode::KEY_DOT))?;
52+
53+
let events = input
54+
.fetch_events()?
55+
.into_iter()
56+
.collect::<Vec<InputEvent>>();
57+
58+
assert_eq!(Some(1), final_event_state(KeyCode::KEY_A, &events));
59+
assert_eq!(Some(1), final_event_state(KeyCode::KEY_B, &events));
60+
61+
Ok(())
62+
}
63+
64+
#[test]
65+
pub fn test_compensate_with_switch_down() -> std::io::Result<()> {
66+
let (mut input, mut output) = get_test_device()?;
67+
68+
let dot_state: i32 = 0;
69+
70+
output.emit(&[InputEvent::new(
71+
EventType::SWITCH.0,
72+
SwitchCode::SW_LID.0,
73+
1,
74+
)])?;
75+
76+
// Make overflow.
77+
for _ in 0..30 {
78+
output.emit(&key_click(KeyCode::KEY_DOT))?;
79+
}
80+
81+
let dot_state = final_dot_state(dot_state, input.fetch_events()?);
82+
83+
assert_eq!(0, dot_state);
84+
85+
// Press and release.
86+
output.emit(&key_click(KeyCode::KEY_DOT))?;
87+
88+
let dot_state = final_dot_state(dot_state, input.fetch_events()?);
89+
90+
assert_eq!(0, dot_state);
91+
92+
Ok(())
93+
}

src/tests/mod.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
mod attribute_set;
2+
mod compensate;
3+
4+
use crate::uinput::VirtualDevice;
5+
use crate::{AttributeSet, BusType, Device, EventType, InputEvent, InputId, KeyCode, SwitchCode};
6+
use std::path::PathBuf;
7+
use std::thread;
8+
use std::time::Duration;
9+
10+
pub fn key_click(key: KeyCode) -> Vec<InputEvent> {
11+
vec![key_event(key, 1), key_event(key, 0)]
12+
}
13+
14+
pub fn key_event(key: KeyCode, key_state: i32) -> InputEvent {
15+
InputEvent::new(EventType::KEY.0, key.code(), key_state)
16+
}
17+
18+
pub fn get_test_device() -> std::io::Result<(Device, VirtualDevice)> {
19+
let (name, output) = get_device()?;
20+
21+
let mut input = Device::open(&name)?;
22+
23+
input.grab()?;
24+
25+
Ok((input, output))
26+
}
27+
28+
pub fn get_device() -> std::io::Result<(PathBuf, VirtualDevice)> {
29+
let mut keys: AttributeSet<KeyCode> = AttributeSet::new();
30+
for code in 1..59 {
31+
let key = KeyCode::new(code);
32+
let name = format!("{:?}", key);
33+
if name.starts_with("KEY_") {
34+
keys.insert(key);
35+
}
36+
}
37+
38+
let mut sw: AttributeSet<SwitchCode> = AttributeSet::new();
39+
40+
sw.insert(SwitchCode::SW_LID);
41+
sw.insert(SwitchCode::SW_TABLET_MODE);
42+
43+
let mut device = VirtualDevice::builder()?
44+
.input_id(InputId::new(BusType::BUS_USB, 0x1234, 0x5678, 0x111))
45+
.name("test device")
46+
.with_keys(&keys)?
47+
.with_switches(&sw)?
48+
.build()?;
49+
50+
// Fetch name.
51+
let d: Vec<std::path::PathBuf> = device
52+
.enumerate_dev_nodes_blocking()?
53+
.map(|p| p.unwrap())
54+
.collect();
55+
56+
thread::sleep(Duration::from_millis(100)); // To avoid permission denied.
57+
58+
Ok((d.first().unwrap().clone(), device))
59+
}
60+
61+
pub fn final_dot_state(start_state: i32, events: impl Iterator<Item = InputEvent>) -> i32 {
62+
events.fold(start_state, |state, ev| {
63+
if ev.event_type() == EventType::KEY && ev.code() == KeyCode::KEY_DOT.code() {
64+
if ev.value() == 0 {
65+
0
66+
} else {
67+
1
68+
}
69+
} else {
70+
state
71+
}
72+
})
73+
}
74+
75+
pub fn final_event_state(key: KeyCode, events: &Vec<InputEvent>) -> Option<i32> {
76+
events.iter().fold(None, |state, ev| {
77+
if ev.event_type() == EventType::KEY && ev.code() == key.code() {
78+
if ev.value() == 0 {
79+
Some(0)
80+
} else {
81+
Some(1)
82+
}
83+
} else {
84+
state
85+
}
86+
})
87+
}

0 commit comments

Comments
 (0)