1use input_event::{Event as InputEvent, KeyboardEvent, PointerEvent};
2use num_enum::{IntoPrimitive, TryFromPrimitive, TryFromPrimitiveError};
3use paste::paste;
4use std::{
5 fmt::{Debug, Display},
6 mem::size_of,
7};
8use thiserror::Error;
9
10pub const MAX_EVENT_SIZE: usize = size_of::<u8>() + size_of::<u32>() + 2 * size_of::<f64>();
14
15#[derive(Debug, Error)]
17pub enum ProtocolError {
18 #[error("invalid event id: `{0}`")]
20 InvalidEventId(#[from] TryFromPrimitiveError<EventType>),
21}
22
23#[derive(Clone, Copy, Debug)]
25pub enum ProtoEvent {
26 Enter(u32),
29 Leave(u32),
32 Ack(u32),
34 Input(InputEvent),
36 Ping,
39 Pong,
41}
42
43impl Display for ProtoEvent {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match self {
46 ProtoEvent::Enter(s) => write!(f, "Enter({s})"),
47 ProtoEvent::Leave(s) => write!(f, "Leave({s})"),
48 ProtoEvent::Ack(s) => write!(f, "Ack({s})"),
49 ProtoEvent::Input(e) => write!(f, "{e}"),
50 ProtoEvent::Ping => write!(f, "ping"),
51 ProtoEvent::Pong => write!(f, "pong"),
52 }
53 }
54}
55
56#[derive(TryFromPrimitive, IntoPrimitive)]
57#[repr(u8)]
58pub enum EventType {
59 PointerMotion,
60 PointerButton,
61 PointerAxis,
62 PointerAxisValue120,
63 KeyboardKey,
64 KeyboardModifiers,
65 Ping,
66 Pong,
67 Enter,
68 Leave,
69 Ack,
70}
71
72impl ProtoEvent {
73 fn event_type(&self) -> EventType {
74 match self {
75 ProtoEvent::Input(e) => match e {
76 InputEvent::Pointer(p) => match p {
77 PointerEvent::Motion { .. } => EventType::PointerMotion,
78 PointerEvent::Button { .. } => EventType::PointerButton,
79 PointerEvent::Axis { .. } => EventType::PointerAxis,
80 PointerEvent::AxisDiscrete120 { .. } => EventType::PointerAxisValue120,
81 },
82 InputEvent::Keyboard(k) => match k {
83 KeyboardEvent::Key { .. } => EventType::KeyboardKey,
84 KeyboardEvent::Modifiers { .. } => EventType::KeyboardModifiers,
85 },
86 },
87 ProtoEvent::Ping => EventType::Ping,
88 ProtoEvent::Pong => EventType::Pong,
89 ProtoEvent::Enter(_) => EventType::Enter,
90 ProtoEvent::Leave(_) => EventType::Leave,
91 ProtoEvent::Ack(_) => EventType::Ack,
92 }
93 }
94}
95
96impl TryFrom<[u8; MAX_EVENT_SIZE]> for ProtoEvent {
97 type Error = ProtocolError;
98
99 fn try_from(buf: [u8; MAX_EVENT_SIZE]) -> Result<Self, Self::Error> {
100 let mut buf = &buf[..];
101 let event_type = decode_u8(&mut buf)?;
102 match EventType::try_from(event_type)? {
103 EventType::PointerMotion => {
104 Ok(Self::Input(InputEvent::Pointer(PointerEvent::Motion {
105 time: decode_u32(&mut buf)?,
106 dx: decode_f64(&mut buf)?,
107 dy: decode_f64(&mut buf)?,
108 })))
109 }
110 EventType::PointerButton => {
111 Ok(Self::Input(InputEvent::Pointer(PointerEvent::Button {
112 time: decode_u32(&mut buf)?,
113 button: decode_u32(&mut buf)?,
114 state: decode_u32(&mut buf)?,
115 })))
116 }
117 EventType::PointerAxis => Ok(Self::Input(InputEvent::Pointer(PointerEvent::Axis {
118 time: decode_u32(&mut buf)?,
119 axis: decode_u8(&mut buf)?,
120 value: decode_f64(&mut buf)?,
121 }))),
122 EventType::PointerAxisValue120 => Ok(Self::Input(InputEvent::Pointer(
123 PointerEvent::AxisDiscrete120 {
124 axis: decode_u8(&mut buf)?,
125 value: decode_i32(&mut buf)?,
126 },
127 ))),
128 EventType::KeyboardKey => Ok(Self::Input(InputEvent::Keyboard(KeyboardEvent::Key {
129 time: decode_u32(&mut buf)?,
130 key: decode_u32(&mut buf)?,
131 state: decode_u8(&mut buf)?,
132 }))),
133 EventType::KeyboardModifiers => Ok(Self::Input(InputEvent::Keyboard(
134 KeyboardEvent::Modifiers {
135 depressed: decode_u32(&mut buf)?,
136 latched: decode_u32(&mut buf)?,
137 locked: decode_u32(&mut buf)?,
138 group: decode_u32(&mut buf)?,
139 },
140 ))),
141 EventType::Ping => Ok(Self::Ping),
142 EventType::Pong => Ok(Self::Pong),
143 EventType::Enter => Ok(Self::Enter(decode_u32(&mut buf)?)),
144 EventType::Leave => Ok(Self::Leave(decode_u32(&mut buf)?)),
145 EventType::Ack => Ok(Self::Ack(decode_u32(&mut buf)?)),
146 }
147 }
148}
149
150impl From<ProtoEvent> for ([u8; MAX_EVENT_SIZE], usize) {
151 fn from(event: ProtoEvent) -> Self {
152 let mut buf = [0u8; MAX_EVENT_SIZE];
153 let mut len = 0usize;
154 {
155 let mut buf = &mut buf[..];
156 let buf = &mut buf;
157 let len = &mut len;
158 encode_u8(buf, len, event.event_type() as u8);
159 match event {
160 ProtoEvent::Input(event) => match event {
161 InputEvent::Pointer(p) => match p {
162 PointerEvent::Motion { time, dx, dy } => {
163 encode_u32(buf, len, time);
164 encode_f64(buf, len, dx);
165 encode_f64(buf, len, dy);
166 }
167 PointerEvent::Button {
168 time,
169 button,
170 state,
171 } => {
172 encode_u32(buf, len, time);
173 encode_u32(buf, len, button);
174 encode_u32(buf, len, state);
175 }
176 PointerEvent::Axis { time, axis, value } => {
177 encode_u32(buf, len, time);
178 encode_u8(buf, len, axis);
179 encode_f64(buf, len, value);
180 }
181 PointerEvent::AxisDiscrete120 { axis, value } => {
182 encode_u8(buf, len, axis);
183 encode_i32(buf, len, value);
184 }
185 },
186 InputEvent::Keyboard(k) => match k {
187 KeyboardEvent::Key { time, key, state } => {
188 encode_u32(buf, len, time);
189 encode_u32(buf, len, key);
190 encode_u8(buf, len, state);
191 }
192 KeyboardEvent::Modifiers {
193 depressed,
194 latched,
195 locked,
196 group,
197 } => {
198 encode_u32(buf, len, depressed);
199 encode_u32(buf, len, latched);
200 encode_u32(buf, len, locked);
201 encode_u32(buf, len, group);
202 }
203 },
204 },
205 ProtoEvent::Ping => {}
206 ProtoEvent::Pong => {}
207 ProtoEvent::Enter(serial) => encode_u32(buf, len, serial),
208 ProtoEvent::Leave(serial) => encode_u32(buf, len, serial),
209 ProtoEvent::Ack(serial) => encode_u32(buf, len, serial),
210 }
211 }
212 (buf, len)
213 }
214}
215
216macro_rules! decode_impl {
217 ($t:ty) => {
218 paste! {
219 fn [<decode_ $t>](data: &mut &[u8]) -> Result<$t, ProtocolError> {
220 let (int_bytes, rest) = data.split_at(size_of::<$t>());
221 *data = rest;
222 Ok($t::from_be_bytes(int_bytes.try_into().unwrap()))
223 }
224 }
225 };
226}
227
228decode_impl!(u8);
229decode_impl!(u32);
230decode_impl!(i32);
231decode_impl!(f64);
232
233macro_rules! encode_impl {
234 ($t:ty) => {
235 paste! {
236 fn [<encode_ $t>](buf: &mut &mut [u8], amt: &mut usize, n: $t) {
237 let src = n.to_be_bytes();
238 let data = std::mem::take(buf);
239 let (int_bytes, rest) = data.split_at_mut(size_of::<$t>());
240 int_bytes.copy_from_slice(&src);
241 *amt += size_of::<$t>();
242 *buf = rest
243 }
244 }
245 };
246}
247
248encode_impl!(u8);
249encode_impl!(u32);
250encode_impl!(i32);
251encode_impl!(f64);