1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::compat::input_absinfo;
use crate::{constants::*, raw_stream::RawDevice};
use crate::{AttributeSet, AttributeSetRef, InputEvent, InputEventKind, Key};
use std::time::SystemTime;

/// A **cached** representation of device state at a certain time.
#[derive(Debug)]
pub struct DeviceState {
    /// The state corresponds to kernel state at this timestamp.
    pub(crate) timestamp: SystemTime,
    /// Set = key pressed
    pub(crate) key_vals: Option<AttributeSet<Key>>,
    pub(crate) abs_vals: Option<Box<[input_absinfo; AbsoluteAxisType::COUNT]>>,
    /// Set = switch enabled (closed)
    pub(crate) switch_vals: Option<AttributeSet<SwitchType>>,
    /// Set = LED lit
    pub(crate) led_vals: Option<AttributeSet<LedType>>,
}

// manual Clone impl for clone_from optimization
impl Clone for DeviceState {
    fn clone(&self) -> Self {
        Self {
            timestamp: self.timestamp,
            key_vals: self.key_vals.clone(),
            abs_vals: self.abs_vals.clone(),
            switch_vals: self.switch_vals.clone(),
            led_vals: self.led_vals.clone(),
        }
    }
    fn clone_from(&mut self, other: &Self) {
        self.timestamp.clone_from(&other.timestamp);
        self.key_vals.clone_from(&other.key_vals);
        self.abs_vals.clone_from(&other.abs_vals);
        self.switch_vals.clone_from(&other.switch_vals);
        self.led_vals.clone_from(&other.led_vals);
    }
}

impl DeviceState {
    /// Create an empty `DeviceState`. The `{abs,key,etc}_vals` for the returned state will return
    /// `Some` if `supported_events()` contains that `EventType`.
    pub(crate) fn new(device: &RawDevice) -> Self {
        let supports = device.supported_events();

        let key_vals = if supports.contains(EventType::KEY) {
            Some(AttributeSet::new())
        } else {
            None
        };
        let abs_vals = if supports.contains(EventType::ABSOLUTE) {
            Some(Box::new(crate::raw_stream::ABS_VALS_INIT))
        } else {
            None
        };
        let switch_vals = if supports.contains(EventType::SWITCH) {
            Some(AttributeSet::new())
        } else {
            None
        };
        let led_vals = if supports.contains(EventType::LED) {
            Some(AttributeSet::new())
        } else {
            None
        };

        DeviceState {
            timestamp: std::time::UNIX_EPOCH,
            key_vals,
            abs_vals,
            switch_vals,
            led_vals,
        }
    }
    /// Returns the time when this snapshot was taken.
    pub fn timestamp(&self) -> SystemTime {
        self.timestamp
    }

    /// Returns the set of keys pressed when the snapshot was taken.
    ///
    /// Returns `None` if keys are not supported by this device.
    pub fn key_vals(&self) -> Option<&AttributeSetRef<Key>> {
        self.key_vals.as_deref()
    }

    /// Returns the set of absolute axis measurements when the snapshot was taken.
    ///
    /// Returns `None` if not supported by this device.
    pub fn abs_vals(&self) -> Option<&[input_absinfo]> {
        self.abs_vals.as_deref().map(|v| &v[..])
    }

    /// Returns the set of switches triggered when the snapshot was taken.
    ///
    /// Returns `None` if switches are not supported by this device.
    pub fn switch_vals(&self) -> Option<&AttributeSetRef<SwitchType>> {
        self.switch_vals.as_deref()
    }

    /// Returns the set of LEDs turned on when the snapshot was taken.
    ///
    /// Returns `None` if LEDs are not supported by this device.
    pub fn led_vals(&self) -> Option<&AttributeSetRef<LedType>> {
        self.led_vals.as_deref()
    }

    #[inline]
    pub(crate) fn process_event(&mut self, ev: InputEvent) {
        match ev.kind() {
            InputEventKind::Key(code) => {
                let keys = self
                    .key_vals
                    .as_deref_mut()
                    .expect("got a key event despite not supporting keys");
                keys.set(code, ev.value() != 0);
            }
            InputEventKind::AbsAxis(axis) => {
                let axes = self
                    .abs_vals
                    .as_deref_mut()
                    .expect("got an abs event despite not supporting absolute axes");
                axes[axis.0 as usize].value = ev.value();
            }
            _ => {}
        }
    }
}