Skip to main content

xmirror_event/
proto.rs

1//! Compact wire protocol for `Event` relying on stable ABI and enum discriminants via #[repr(C)]
2
3use std::io::{self, Write};
4
5use crate::{Event, Key, Mods, Mouse};
6
7impl Event {
8    pub const SIZE: usize = 3;
9
10    #[rustfmt::skip]
11    pub fn encode<W: Write>(self, w: &mut W) -> io::Result<()> {
12        match self {
13            Event::KeyDown(k)   => w.write_all(&[1, k as u8,  0])?,
14            Event::KeyUp(k)     => w.write_all(&[2, k as u8,  0])?,
15            Event::Mods(m)      => w.write_all(&[3, m.bits(), 0])?,
16            Event::MouseDown(b) => w.write_all(&[4, b as u8,  0])?,
17            Event::MouseUp(b)   => w.write_all(&[5, b as u8,  0])?,
18            Event::MouseMove { dx, dy } => w.write_all(&[6, dx as u8, dy as u8])?,
19            Event::Scroll { dx, dy } => w.write_all(&[7, dx as u8, dy as u8])?,
20        }
21        Ok(())
22    }
23
24    pub fn decode(packet: &[u8; Self::SIZE]) -> io::Result<Event> {
25        let [tag, byte0, byte1] = *packet;
26        let bits = byte0;
27        let (dx, dy) = (byte0 as i8, byte1 as i8);
28
29        let ev = match tag {
30            1 => Event::KeyDown(to_key(bits)?),
31            2 => Event::KeyUp(to_key(bits)?),
32            3 => Event::Mods(Mods::from_bits_truncate(bits)),
33            4 => Event::MouseDown(to_button(bits)?),
34            5 => Event::MouseUp(to_button(bits)?),
35            6 => Event::MouseMove { dx, dy },
36            7 => Event::Scroll { dx, dy },
37            _ => return Err(io::ErrorKind::InvalidData.into()),
38        };
39        Ok(ev)
40    }
41}
42
43#[inline]
44fn to_key(byte: u8) -> io::Result<Key> {
45    const KEY_MAX: u8 = Key::F12 as u8 + 1;
46    if byte < KEY_MAX {
47        Ok(unsafe { std::mem::transmute(byte) })
48    } else {
49        Err(io::ErrorKind::InvalidData.into())
50    }
51}
52
53#[inline]
54fn to_button(byte: u8) -> io::Result<Mouse> {
55    const BUTTON_MAX: u8 = Mouse::Middle as u8 + 1;
56    if byte < BUTTON_MAX {
57        Ok(unsafe { std::mem::transmute(byte) })
58    } else {
59        Err(io::ErrorKind::InvalidData.into())
60    }
61}