move lan-mouse protocol to separate crate (#178)

This commit is contained in:
Ferdinand Schober
2024-08-11 16:51:47 +02:00
committed by GitHub
parent fe06ca1fae
commit 19c2c4327f
28 changed files with 451 additions and 545 deletions

View File

@@ -1,17 +1 @@
use std::array::TryFromSliceError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ProtocolError {
#[error(transparent)]
MissingData(#[from] TryFromSliceError),
#[error("invalid event id: `{0}`")]
InvalidEventId(u8),
#[error("invalid pointer event type: `{0}`")]
InvalidPointerEventId(u8),
#[error("invalid keyboard event type: `{0}`")]
InvalidKeyboardEventId(u8),
#[error("expected data at idx `{0:?}`")]
Data(String),
}

View File

@@ -1,8 +1,6 @@
pub use error::ProtocolError;
use std::fmt::{self, Display};
pub mod error;
pub mod proto;
pub mod scancode;
#[cfg(all(unix, feature = "libei", not(target_os = "macos")))]
@@ -25,8 +23,6 @@ pub enum PointerEvent {
Axis { time: u32, axis: u8, value: f64 },
/// discrete axis event, scroll event for mice - 120 = one scroll tick
AxisDiscrete120 { axis: u8, value: i32 },
/// frame event
Frame {},
}
#[derive(Debug, PartialEq, Clone, Copy)]
@@ -35,9 +31,9 @@ pub enum KeyboardEvent {
Key { time: u32, key: u32, state: u8 },
/// modifiers changed state
Modifiers {
mods_depressed: u32,
mods_latched: u32,
mods_locked: u32,
depressed: u32,
latched: u32,
locked: u32,
group: u32,
},
}
@@ -48,23 +44,6 @@ pub enum Event {
Pointer(PointerEvent),
/// keyboard events (key / modifiers)
Keyboard(KeyboardEvent),
/// enter event: request to enter a client.
/// The client must release the pointer if it is grabbed
/// and reply with a leave event, as soon as its ready to
/// receive events
Enter(),
/// leave event: this client is now ready to receive events and will
/// not send any events after until it sends an enter event
Leave(),
/// ping a client, to see if it is still alive. A client that does
/// not respond with a pong event will be assumed to be offline.
Ping(),
/// response to a ping event: this event signals that a client
/// is still alive but must otherwise be ignored
Pong(),
/// explicit disconnect request. The client will no longer
/// send events until the next Enter event. All of its keys should be released.
Disconnect(),
}
impl Display for PointerEvent {
@@ -98,7 +77,6 @@ impl Display for PointerEvent {
PointerEvent::AxisDiscrete120 { axis, value } => {
write!(f, "scroll-120 ({axis}, {value})")
}
PointerEvent::Frame {} => write!(f, "frame()"),
}
}
}
@@ -119,9 +97,9 @@ impl Display for KeyboardEvent {
}
}
KeyboardEvent::Modifiers {
mods_depressed,
mods_latched,
mods_locked,
depressed: mods_depressed,
latched: mods_latched,
locked: mods_locked,
group,
} => write!(
f,
@@ -136,11 +114,6 @@ impl Display for Event {
match self {
Event::Pointer(p) => write!(f, "{}", p),
Event::Keyboard(k) => write!(f, "{}", k),
Event::Enter() => write!(f, "enter"),
Event::Leave() => write!(f, "leave"),
Event::Ping() => write!(f, "ping"),
Event::Pong() => write!(f, "pong"),
Event::Disconnect() => write!(f, "disconnect"),
}
}
}

View File

@@ -57,9 +57,9 @@ fn to_input_events(ei_event: EiEvent) -> Events {
match ei_event {
EiEvent::KeyboardModifiers(mods) => {
let modifier_event = KeyboardEvent::Modifiers {
mods_depressed: mods.depressed,
mods_latched: mods.latched,
mods_locked: mods.locked,
depressed: mods.depressed,
latched: mods.latched,
locked: mods.locked,
group: mods.group,
};
Events::One(Event::Keyboard(modifier_event))

View File

@@ -1,307 +0,0 @@
use std::{fmt::Debug, slice::SliceIndex};
use crate::ProtocolError;
use super::{Event, KeyboardEvent, PointerEvent};
enum PointerEventType {
Motion,
Button,
Axis,
AxisDiscrete120,
Frame,
}
enum KeyboardEventType {
Key,
Modifiers,
}
enum EventType {
Pointer,
Keyboard,
Enter,
Leave,
Ping,
Pong,
Disconnect,
}
impl Event {
fn event_type(&self) -> EventType {
match self {
Self::Pointer(_) => EventType::Pointer,
Self::Keyboard(_) => EventType::Keyboard,
Self::Enter() => EventType::Enter,
Self::Leave() => EventType::Leave,
Self::Ping() => EventType::Ping,
Self::Pong() => EventType::Pong,
Self::Disconnect() => EventType::Disconnect,
}
}
}
impl PointerEvent {
fn event_type(&self) -> PointerEventType {
match self {
Self::Motion { .. } => PointerEventType::Motion,
Self::Button { .. } => PointerEventType::Button,
Self::Axis { .. } => PointerEventType::Axis,
Self::AxisDiscrete120 { .. } => PointerEventType::AxisDiscrete120,
Self::Frame { .. } => PointerEventType::Frame,
}
}
}
impl KeyboardEvent {
fn event_type(&self) -> KeyboardEventType {
match self {
KeyboardEvent::Key { .. } => KeyboardEventType::Key,
KeyboardEvent::Modifiers { .. } => KeyboardEventType::Modifiers,
}
}
}
impl TryFrom<u8> for PointerEventType {
type Error = ProtocolError;
fn try_from(value: u8) -> Result<Self, ProtocolError> {
match value {
x if x == Self::Motion as u8 => Ok(Self::Motion),
x if x == Self::Button as u8 => Ok(Self::Button),
x if x == Self::Axis as u8 => Ok(Self::Axis),
x if x == Self::AxisDiscrete120 as u8 => Ok(Self::AxisDiscrete120),
x if x == Self::Frame as u8 => Ok(Self::Frame),
_ => Err(ProtocolError::InvalidPointerEventId(value)),
}
}
}
impl TryFrom<u8> for KeyboardEventType {
type Error = ProtocolError;
fn try_from(value: u8) -> Result<Self, ProtocolError> {
match value {
x if x == Self::Key as u8 => Ok(Self::Key),
x if x == Self::Modifiers as u8 => Ok(Self::Modifiers),
_ => Err(ProtocolError::InvalidKeyboardEventId(value)),
}
}
}
impl From<&Event> for Vec<u8> {
fn from(event: &Event) -> Self {
let event_id = vec![event.event_type() as u8];
let event_data = match event {
Event::Pointer(p) => p.into(),
Event::Keyboard(k) => k.into(),
Event::Enter() => vec![],
Event::Leave() => vec![],
Event::Ping() => vec![],
Event::Pong() => vec![],
Event::Disconnect() => vec![],
};
[event_id, event_data].concat()
}
}
impl TryFrom<Vec<u8>> for Event {
type Error = ProtocolError;
fn try_from(value: Vec<u8>) -> Result<Self, ProtocolError> {
let event_id = u8::from_be_bytes(value[..1].try_into()?);
match event_id {
i if i == (EventType::Pointer as u8) => Ok(Event::Pointer(value.try_into()?)),
i if i == (EventType::Keyboard as u8) => Ok(Event::Keyboard(value.try_into()?)),
i if i == (EventType::Enter as u8) => Ok(Event::Enter()),
i if i == (EventType::Leave as u8) => Ok(Event::Leave()),
i if i == (EventType::Ping as u8) => Ok(Event::Ping()),
i if i == (EventType::Pong as u8) => Ok(Event::Pong()),
i if i == (EventType::Disconnect as u8) => Ok(Event::Disconnect()),
_ => Err(ProtocolError::InvalidEventId(event_id)),
}
}
}
impl From<&PointerEvent> for Vec<u8> {
fn from(event: &PointerEvent) -> Self {
let id = vec![event.event_type() as u8];
let data = match event {
PointerEvent::Motion { time, dx, dy } => {
let time = time.to_be_bytes();
let dx = dx.to_be_bytes();
let dy = dy.to_be_bytes();
[&time[..], &dx[..], &dy[..]].concat()
}
PointerEvent::Button {
time,
button,
state,
} => {
let time = time.to_be_bytes();
let button = button.to_be_bytes();
let state = state.to_be_bytes();
[&time[..], &button[..], &state[..]].concat()
}
PointerEvent::Axis { time, axis, value } => {
let time = time.to_be_bytes();
let axis = axis.to_be_bytes();
let value = value.to_be_bytes();
[&time[..], &axis[..], &value[..]].concat()
}
PointerEvent::AxisDiscrete120 { axis, value } => {
let axis = axis.to_be_bytes();
let value = value.to_be_bytes();
[&axis[..], &value[..]].concat()
}
PointerEvent::Frame {} => {
vec![]
}
};
[id, data].concat()
}
}
fn decode_u8<I>(data: &[u8], idx: I) -> Result<u8, ProtocolError>
where
I: SliceIndex<[u8], Output = [u8]> + Debug + Clone,
{
let data = data
.get(idx.clone())
.ok_or(ProtocolError::Data(format!("{:?}", idx)))?;
Ok(u8::from_be_bytes(data.try_into()?))
}
fn decode_u32<I>(data: &[u8], idx: I) -> Result<u32, ProtocolError>
where
I: SliceIndex<[u8], Output = [u8]> + Debug + Clone,
{
let data = data
.get(idx.clone())
.ok_or(ProtocolError::Data(format!("{:?}", idx)))?;
Ok(u32::from_be_bytes(data.try_into()?))
}
fn decode_i32<I>(data: &[u8], idx: I) -> Result<i32, ProtocolError>
where
I: SliceIndex<[u8], Output = [u8]> + Debug + Clone,
{
let data = data
.get(idx.clone())
.ok_or(ProtocolError::Data(format!("{:?}", idx)))?;
Ok(i32::from_be_bytes(data.try_into()?))
}
fn decode_f64<I>(data: &[u8], idx: I) -> Result<f64, ProtocolError>
where
I: SliceIndex<[u8], Output = [u8]> + Debug + Clone,
{
let data = data
.get(idx.clone())
.ok_or(ProtocolError::Data(format!("{:?}", idx)))?;
Ok(f64::from_be_bytes(data.try_into()?))
}
impl TryFrom<Vec<u8>> for PointerEvent {
type Error = ProtocolError;
fn try_from(data: Vec<u8>) -> Result<Self, ProtocolError> {
match data.get(1) {
Some(id) => match id.to_owned().try_into()? {
PointerEventType::Motion => {
let time = decode_u32(&data, 2..6)?;
let dx = decode_f64(&data, 6..14)?;
let dy = decode_f64(&data, 14..22)?;
Ok(Self::Motion { time, dx, dy })
}
PointerEventType::Button => {
let time = decode_u32(&data, 2..6)?;
let button = decode_u32(&data, 6..10)?;
let state = decode_u32(&data, 10..14)?;
Ok(Self::Button {
time,
button,
state,
})
}
PointerEventType::Axis => {
let time = decode_u32(&data, 2..6)?;
let axis = decode_u8(&data, 6..7)?;
let value = decode_f64(&data, 7..15)?;
Ok(Self::Axis { time, axis, value })
}
PointerEventType::AxisDiscrete120 => {
let axis = decode_u8(&data, 2..3)?;
let value = decode_i32(&data, 3..7)?;
Ok(Self::AxisDiscrete120 { axis, value })
}
PointerEventType::Frame => Ok(Self::Frame {}),
},
None => Err(ProtocolError::Data("0".to_string())),
}
}
}
impl From<&KeyboardEvent> for Vec<u8> {
fn from(event: &KeyboardEvent) -> Self {
let id = vec![event.event_type() as u8];
let data = match event {
KeyboardEvent::Key { time, key, state } => {
let time = time.to_be_bytes();
let key = key.to_be_bytes();
let state = state.to_be_bytes();
[&time[..], &key[..], &state[..]].concat()
}
KeyboardEvent::Modifiers {
mods_depressed,
mods_latched,
mods_locked,
group,
} => {
let mods_depressed = mods_depressed.to_be_bytes();
let mods_latched = mods_latched.to_be_bytes();
let mods_locked = mods_locked.to_be_bytes();
let group = group.to_be_bytes();
[
&mods_depressed[..],
&mods_latched[..],
&mods_locked[..],
&group[..],
]
.concat()
}
};
[id, data].concat()
}
}
impl TryFrom<Vec<u8>> for KeyboardEvent {
type Error = ProtocolError;
fn try_from(data: Vec<u8>) -> Result<Self, ProtocolError> {
match data.get(1) {
Some(id) => match id.to_owned().try_into()? {
KeyboardEventType::Key => {
let time = decode_u32(&data, 2..6)?;
let key = decode_u32(&data, 6..10)?;
let state = decode_u8(&data, 10..11)?;
Ok(KeyboardEvent::Key { time, key, state })
}
KeyboardEventType::Modifiers => {
let mods_depressed = decode_u32(&data, 2..6)?;
let mods_latched = decode_u32(&data, 6..10)?;
let mods_locked = decode_u32(&data, 10..14)?;
let group = decode_u32(&data, 14..18)?;
Ok(KeyboardEvent::Modifiers {
mods_depressed,
mods_latched,
mods_locked,
group,
})
}
},
None => Err(ProtocolError::Data("0".to_string())),
}
}
}