1use std::fmt::{self, Display, Formatter};
2
3use derive_more::{Display, LowerHex, UpperHex};
4
5use crate::{Address, Data, Frame, MsgType};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30#[non_exhaustive]
31pub enum Message<'a> {
32 SendData(Offset, Data<'a>),
38 DataChunksSent(ChunkCount),
42
43 Hello(Address),
47 QueryState(Address),
51 ReportState(Address, State),
55
56 RequestOperation(Address, Operation),
60 AckOperation(Address, Operation),
63
64 PixelsComplete(Address),
70
71 Goodbye(Address),
77
78 Unknown(Frame<'a>),
80}
81
82#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Display, LowerHex, UpperHex)]
99pub struct Offset(pub u16);
100
101#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Display, LowerHex, UpperHex)]
112pub struct ChunkCount(pub u16);
113
114#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
119#[non_exhaustive]
120pub enum State {
121 Unconfigured,
124 ConfigInProgress,
126 ConfigReceived,
128 ConfigFailed,
130 PixelsInProgress,
132 PixelsReceived,
134 PixelsFailed,
136 PageLoaded,
138 PageLoadInProgress,
140 PageShown,
142 PageShowInProgress,
144 ShowingPages,
147 ReadyToReset,
149}
150
151#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
155#[non_exhaustive]
156pub enum Operation {
157 ReceiveConfig,
159 ReceivePixels,
161 ShowLoadedPage,
163 LoadNextPage,
165 StartReset,
167 FinishReset,
169}
170
171impl Display for Message<'_> {
172 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
176 match *self {
177 Message::SendData(offset, ref data) => {
178 write!(f, "SendData [Offset {:04X}] ", offset)?;
179 for byte in data.get().iter() {
180 write!(f, "{:02X} ", byte)?;
181 }
182 }
183
184 Message::DataChunksSent(chunks) => write!(f, "DataChunksSent [{:04X}]", chunks)?,
185
186 Message::Hello(address) => write!(f, "[Addr {:04X}] <-- Hello", address)?,
187 Message::QueryState(address) => write!(f, "[Addr {:04X}] <-- QueryState", address)?,
188 Message::ReportState(address, state) => write!(f, "[Addr {:04X}] --> ReportState [{:?}]", address, state)?,
189
190 Message::RequestOperation(address, op) => write!(f, "[Addr {:04X}] <-- RequestOperation [{:?}]", address, op)?,
191 Message::AckOperation(address, op) => write!(f, "[Addr {:04X}] --> AckOperation [{:?}]", address, op)?,
192
193 Message::PixelsComplete(address) => write!(f, "[Addr {:04X}] <-- PixelsComplete", address)?,
194
195 Message::Goodbye(address) => write!(f, "[Addr {:04X}] <-- Goodbye", address)?,
196
197 Message::Unknown(ref frame) => write!(f, "Unknown {}", frame)?,
198 }
199
200 Ok(())
201 }
202}
203
204impl<'a> From<Frame<'a>> for Message<'a> {
205 fn from(frame: Frame<'a>) -> Self {
223 match frame.data().len() {
224 0 => match frame.message_type() {
225 MsgType(1) => Message::DataChunksSent(ChunkCount(frame.address().0)),
226 _ => Message::Unknown(frame),
227 },
228
229 1 => match (frame.message_type(), frame.data()[0]) {
230 (MsgType(2), 0xFF) => Message::Hello(frame.address()),
231 (MsgType(2), 0x00) => Message::QueryState(frame.address()),
232 (MsgType(2), 0x55) => Message::Goodbye(frame.address()),
233
234 (MsgType(4), 0x0F) => Message::ReportState(frame.address(), State::Unconfigured),
235 (MsgType(4), 0x0D) => Message::ReportState(frame.address(), State::ConfigInProgress),
236 (MsgType(4), 0x07) => Message::ReportState(frame.address(), State::ConfigReceived),
237 (MsgType(4), 0x0C) => Message::ReportState(frame.address(), State::ConfigFailed),
238 (MsgType(4), 0x03) => Message::ReportState(frame.address(), State::PixelsInProgress),
239 (MsgType(4), 0x01) => Message::ReportState(frame.address(), State::PixelsReceived),
240 (MsgType(4), 0x0B) => Message::ReportState(frame.address(), State::PixelsFailed),
241 (MsgType(4), 0x10) => Message::ReportState(frame.address(), State::PageLoaded),
242 (MsgType(4), 0x13) => Message::ReportState(frame.address(), State::PageLoadInProgress),
243 (MsgType(4), 0x12) => Message::ReportState(frame.address(), State::PageShown),
244 (MsgType(4), 0x11) => Message::ReportState(frame.address(), State::PageShowInProgress),
245 (MsgType(4), 0x00) => Message::ReportState(frame.address(), State::ShowingPages),
246 (MsgType(4), 0x08) => Message::ReportState(frame.address(), State::ReadyToReset),
247
248 (MsgType(3), 0xA1) => Message::RequestOperation(frame.address(), Operation::ReceiveConfig),
249 (MsgType(3), 0xA2) => Message::RequestOperation(frame.address(), Operation::ReceivePixels),
250 (MsgType(3), 0xA9) => Message::RequestOperation(frame.address(), Operation::ShowLoadedPage),
251 (MsgType(3), 0xAA) => Message::RequestOperation(frame.address(), Operation::LoadNextPage),
252 (MsgType(3), 0xA6) => Message::RequestOperation(frame.address(), Operation::StartReset),
253 (MsgType(3), 0xA7) => Message::RequestOperation(frame.address(), Operation::FinishReset),
254
255 (MsgType(5), 0x95) => Message::AckOperation(frame.address(), Operation::ReceiveConfig),
256 (MsgType(5), 0x91) => Message::AckOperation(frame.address(), Operation::ReceivePixels),
257 (MsgType(5), 0x96) => Message::AckOperation(frame.address(), Operation::ShowLoadedPage),
258 (MsgType(5), 0x97) => Message::AckOperation(frame.address(), Operation::LoadNextPage),
259 (MsgType(5), 0x93) => Message::AckOperation(frame.address(), Operation::StartReset),
260 (MsgType(5), 0x94) => Message::AckOperation(frame.address(), Operation::FinishReset),
261
262 (MsgType(6), 0x00) => Message::PixelsComplete(frame.address()),
263
264 (_, _) => Message::Unknown(frame),
265 },
266
267 _ => match frame.message_type() {
268 MsgType(0) => Message::SendData(Offset(frame.address().0), frame.into_data()),
269 _ => Message::Unknown(frame),
270 },
271 }
272 }
273}
274
275impl<'a> From<Message<'a>> for Frame<'a> {
276 fn from(message: Message<'a>) -> Self {
294 match message {
295 Message::SendData(Offset(offset), data) => Frame::new(Address(offset), MsgType(0), data),
296
297 Message::DataChunksSent(ChunkCount(chunks)) => Frame::new(Address(chunks), MsgType(1), Data::from(&[])),
298
299 Message::Hello(address) => Frame::new(address, MsgType(2), Data::from(&[0xFF])),
300 Message::Goodbye(address) => Frame::new(address, MsgType(2), Data::from(&[0x55])),
301 Message::QueryState(address) => Frame::new(address, MsgType(2), Data::from(&[0x00])),
302
303 Message::ReportState(address, State::Unconfigured) => Frame::new(address, MsgType(4), Data::from(&[0x0F])),
304 Message::ReportState(address, State::ConfigInProgress) => Frame::new(address, MsgType(4), Data::from(&[0x0D])),
305 Message::ReportState(address, State::ConfigReceived) => Frame::new(address, MsgType(4), Data::from(&[0x07])),
306 Message::ReportState(address, State::ConfigFailed) => Frame::new(address, MsgType(4), Data::from(&[0x0C])),
307 Message::ReportState(address, State::PixelsInProgress) => Frame::new(address, MsgType(4), Data::from(&[0x03])),
308 Message::ReportState(address, State::PixelsReceived) => Frame::new(address, MsgType(4), Data::from(&[0x01])),
309 Message::ReportState(address, State::PixelsFailed) => Frame::new(address, MsgType(4), Data::from(&[0x0B])),
310 Message::ReportState(address, State::PageLoaded) => Frame::new(address, MsgType(4), Data::from(&[0x10])),
311 Message::ReportState(address, State::PageLoadInProgress) => Frame::new(address, MsgType(4), Data::from(&[0x13])),
312 Message::ReportState(address, State::PageShown) => Frame::new(address, MsgType(4), Data::from(&[0x12])),
313 Message::ReportState(address, State::PageShowInProgress) => Frame::new(address, MsgType(4), Data::from(&[0x11])),
314 Message::ReportState(address, State::ShowingPages) => Frame::new(address, MsgType(4), Data::from(&[0x00])),
315 Message::ReportState(address, State::ReadyToReset) => Frame::new(address, MsgType(4), Data::from(&[0x08])),
316
317 Message::RequestOperation(address, Operation::ReceiveConfig) => Frame::new(address, MsgType(3), Data::from(&[0xA1])),
318 Message::RequestOperation(address, Operation::ReceivePixels) => Frame::new(address, MsgType(3), Data::from(&[0xA2])),
319 Message::RequestOperation(address, Operation::ShowLoadedPage) => Frame::new(address, MsgType(3), Data::from(&[0xA9])),
320 Message::RequestOperation(address, Operation::LoadNextPage) => Frame::new(address, MsgType(3), Data::from(&[0xAA])),
321 Message::RequestOperation(address, Operation::StartReset) => Frame::new(address, MsgType(3), Data::from(&[0xA6])),
322 Message::RequestOperation(address, Operation::FinishReset) => Frame::new(address, MsgType(3), Data::from(&[0xA7])),
323
324 Message::AckOperation(address, Operation::ReceiveConfig) => Frame::new(address, MsgType(5), Data::from(&[0x95])),
325 Message::AckOperation(address, Operation::ReceivePixels) => Frame::new(address, MsgType(5), Data::from(&[0x91])),
326 Message::AckOperation(address, Operation::ShowLoadedPage) => Frame::new(address, MsgType(5), Data::from(&[0x96])),
327 Message::AckOperation(address, Operation::LoadNextPage) => Frame::new(address, MsgType(5), Data::from(&[0x97])),
328 Message::AckOperation(address, Operation::StartReset) => Frame::new(address, MsgType(5), Data::from(&[0x93])),
329 Message::AckOperation(address, Operation::FinishReset) => Frame::new(address, MsgType(5), Data::from(&[0x94])),
330
331 Message::PixelsComplete(address) => Frame::new(address, MsgType(6), Data::from(&[0x00])),
332
333 Message::Unknown(frame) => frame,
334 }
335 }
336}
337
338#[cfg(test)]
339mod tests {
340 use super::*;
341
342 fn verify_roundtrip(frame: Frame<'_>, expected_message: Message<'_>) {
343 let orig_frame = frame.clone();
344
345 let converted_message = Message::from(frame);
346 assert_eq!(expected_message, converted_message);
347
348 let converted_frame = Frame::from(converted_message);
349 assert_eq!(orig_frame, converted_frame);
350 }
351
352 #[test]
353 fn frame_message_roundtrip() {
354 verify_roundtrip(
355 Frame::new(Address(16), MsgType(0), Data::from(&[0x00, 0x15, 0x51, 0xF7])),
356 Message::SendData(Offset(16), Data::from(&[0x00, 0x15, 0x51, 0xF7])),
357 );
358
359 verify_roundtrip(
360 Frame::new(Address(13), MsgType(1), Data::from(&[])),
361 Message::DataChunksSent(ChunkCount(13)),
362 );
363
364 verify_roundtrip(
365 Frame::new(Address(0x7F), MsgType(2), Data::from(&[0xFF])),
366 Message::Hello(Address(0x7F)),
367 );
368 verify_roundtrip(
369 Frame::new(Address(0x11), MsgType(2), Data::from(&[0x55])),
370 Message::Goodbye(Address(0x11)),
371 );
372 verify_roundtrip(
373 Frame::new(Address(0xFF), MsgType(2), Data::from(&[0x00])),
374 Message::QueryState(Address(0xFF)),
375 );
376
377 verify_roundtrip(
378 Frame::new(Address(0x01), MsgType(4), Data::from(&[0x0F])),
379 Message::ReportState(Address(0x01), State::Unconfigured),
380 );
381
382 verify_roundtrip(
383 Frame::new(Address(0x00), MsgType(3), Data::from(&[0xA1])),
384 Message::RequestOperation(Address(0x00), Operation::ReceiveConfig),
385 );
386 verify_roundtrip(
387 Frame::new(Address(0x01), MsgType(3), Data::from(&[0xA2])),
388 Message::RequestOperation(Address(0x01), Operation::ReceivePixels),
389 );
390 verify_roundtrip(
391 Frame::new(Address(0x11), MsgType(3), Data::from(&[0xA9])),
392 Message::RequestOperation(Address(0x11), Operation::ShowLoadedPage),
393 );
394 verify_roundtrip(
395 Frame::new(Address(0x02), MsgType(3), Data::from(&[0xAA])),
396 Message::RequestOperation(Address(0x02), Operation::LoadNextPage),
397 );
398 verify_roundtrip(
399 Frame::new(Address(0x22), MsgType(3), Data::from(&[0xA6])),
400 Message::RequestOperation(Address(0x22), Operation::StartReset),
401 );
402 verify_roundtrip(
403 Frame::new(Address(0x03), MsgType(3), Data::from(&[0xA7])),
404 Message::RequestOperation(Address(0x03), Operation::FinishReset),
405 );
406
407 verify_roundtrip(
408 Frame::new(Address(0xFF), MsgType(4), Data::from(&[0x0F])),
409 Message::ReportState(Address(0xFF), State::Unconfigured),
410 );
411 verify_roundtrip(
412 Frame::new(Address(0x91), MsgType(4), Data::from(&[0x0D])),
413 Message::ReportState(Address(0x91), State::ConfigInProgress),
414 );
415 verify_roundtrip(
416 Frame::new(Address(0xDC), MsgType(4), Data::from(&[0x07])),
417 Message::ReportState(Address(0xDC), State::ConfigReceived),
418 );
419 verify_roundtrip(
420 Frame::new(Address(0xA1), MsgType(4), Data::from(&[0x0C])),
421 Message::ReportState(Address(0xA1), State::ConfigFailed),
422 );
423 verify_roundtrip(
424 Frame::new(Address(0xF7), MsgType(4), Data::from(&[0x03])),
425 Message::ReportState(Address(0xF7), State::PixelsInProgress),
426 );
427 verify_roundtrip(
428 Frame::new(Address(0x0F), MsgType(4), Data::from(&[0x01])),
429 Message::ReportState(Address(0x0F), State::PixelsReceived),
430 );
431 verify_roundtrip(
432 Frame::new(Address(0x37), MsgType(4), Data::from(&[0x0B])),
433 Message::ReportState(Address(0x37), State::PixelsFailed),
434 );
435 verify_roundtrip(
436 Frame::new(Address(0x42), MsgType(4), Data::from(&[0x10])),
437 Message::ReportState(Address(0x42), State::PageLoaded),
438 );
439 verify_roundtrip(
440 Frame::new(Address(0x68), MsgType(4), Data::from(&[0x13])),
441 Message::ReportState(Address(0x68), State::PageLoadInProgress),
442 );
443 verify_roundtrip(
444 Frame::new(Address(0x1C), MsgType(4), Data::from(&[0x12])),
445 Message::ReportState(Address(0x1C), State::PageShown),
446 );
447 verify_roundtrip(
448 Frame::new(Address(0x9D), MsgType(4), Data::from(&[0x11])),
449 Message::ReportState(Address(0x9D), State::PageShowInProgress),
450 );
451 verify_roundtrip(
452 Frame::new(Address(0x87), MsgType(4), Data::from(&[0x08])),
453 Message::ReportState(Address(0x87), State::ReadyToReset),
454 );
455
456 verify_roundtrip(
457 Frame::new(Address(0xABCD), MsgType(5), Data::from(&[0x95])),
458 Message::AckOperation(Address(0xABCD), Operation::ReceiveConfig),
459 );
460 verify_roundtrip(
461 Frame::new(Address(0xFF00), MsgType(5), Data::from(&[0x91])),
462 Message::AckOperation(Address(0xFF00), Operation::ReceivePixels),
463 );
464 verify_roundtrip(
465 Frame::new(Address(0x0C0F), MsgType(5), Data::from(&[0x96])),
466 Message::AckOperation(Address(0x0C0F), Operation::ShowLoadedPage),
467 );
468 verify_roundtrip(
469 Frame::new(Address(0x11DD), MsgType(5), Data::from(&[0x97])),
470 Message::AckOperation(Address(0x11DD), Operation::LoadNextPage),
471 );
472 verify_roundtrip(
473 Frame::new(Address(0x1337), MsgType(5), Data::from(&[0x93])),
474 Message::AckOperation(Address(0x1337), Operation::StartReset),
475 );
476 verify_roundtrip(
477 Frame::new(Address(0x1987), MsgType(5), Data::from(&[0x94])),
478 Message::AckOperation(Address(0x1987), Operation::FinishReset),
479 );
480
481 verify_roundtrip(
482 Frame::new(Address(0xFFFF), MsgType(6), Data::from(&[0x00])),
483 Message::PixelsComplete(Address(0xFFFF)),
484 );
485
486 verify_roundtrip(
487 Frame::new(Address(0xF00D), MsgType(99), Data::from(&[])),
488 Message::Unknown(Frame::new(Address(0xF00D), MsgType(99), Data::from(&[]))),
489 );
490
491 verify_roundtrip(
492 Frame::new(Address(0xBEEF), MsgType(255), Data::from(&[0xAA])),
493 Message::Unknown(Frame::new(Address(0xBEEF), MsgType(255), Data::from(&[0xAA]))),
494 );
495
496 verify_roundtrip(
497 Frame::new(Address(0xABAB), MsgType(17), Data::from(&[0x7A, 0x1C])),
498 Message::Unknown(Frame::new(Address(0xABAB), MsgType(17), Data::from(&[0x7A, 0x1C]))),
499 );
500 }
501
502 #[test]
503 fn display() {
504 let message = Message::SendData(Offset(0x10), Data::from(&[0x20, 0xFF]));
505 let display = format!("{}", message);
506 assert_eq!("SendData [Offset 0010] 20 FF", display.trim());
507
508 let message = Message::DataChunksSent(ChunkCount(3));
509 let display = format!("{}", message);
510 assert_eq!("DataChunksSent [0003]", display);
511
512 let message = Message::Hello(Address(0x7F));
513 let display = format!("{}", message);
514 assert_eq!("[Addr 007F] <-- Hello", display);
515
516 let message = Message::QueryState(Address(5));
517 let display = format!("{}", message);
518 assert_eq!("[Addr 0005] <-- QueryState", display);
519
520 let message = Message::ReportState(Address(7), State::Unconfigured);
521 let display = format!("{}", message);
522 assert_eq!("[Addr 0007] --> ReportState [Unconfigured]", display);
523
524 let message = Message::RequestOperation(Address(16), Operation::ReceivePixels);
525 let display = format!("{}", message);
526 assert_eq!("[Addr 0010] <-- RequestOperation [ReceivePixels]", display);
527
528 let message = Message::AckOperation(Address(17), Operation::FinishReset);
529 let display = format!("{}", message);
530 assert_eq!("[Addr 0011] --> AckOperation [FinishReset]", display);
531
532 let message = Message::PixelsComplete(Address(32));
533 let display = format!("{}", message);
534 assert_eq!("[Addr 0020] <-- PixelsComplete", display);
535
536 let message = Message::Goodbye(Address(1));
537 let display = format!("{}", message);
538 assert_eq!("[Addr 0001] <-- Goodbye", display);
539
540 let message = Message::Unknown(Frame::new(Address(1), MsgType(2), Data::from(&[])));
541 let display = format!("{}", message);
542 assert_eq!("Unknown Type 02 | Addr 0001", display);
543
544 let message = Message::Unknown(Frame::new(Address(1), MsgType(2), Data::from(&[0x0B, 0x1C])));
545 let display = format!("{}", message);
546 assert_eq!("Unknown Type 02 | Addr 0001 | Data 0B 1C ", display);
547 }
548}