use std::{ io::Cursor, }; use crate::tlv; use thiserror::Error; const MAGIC_NUMBER: [u8; 4] = [0x9a, 0x4a, 0x43, 0x81]; pub const PACKET_SIZE: usize = 1024; #[derive (Debug)] pub enum Message { Request { idem_id: [u8; 8], mac: Option <[u8; 6]> }, Response (Option <[u8; 6]>), } #[derive (Debug, Error)] pub enum MessageError { #[error (transparent)] Io (#[from] std::io::Error), #[error (transparent)] Tlv (#[from] tlv::TlvError), #[error ("Unknown type")] UnknownType, } impl Message { pub fn write (&self, w: &mut W) -> Result <(), std::io::Error> { w.write_all (&MAGIC_NUMBER)?; match self { Self::Request { idem_id, mac, }=> { w.write_all (&[1])?; w.write_all (&idem_id[..])?; Self::write_mac_opt (w, *mac)?; }, Self::Response (mac) => { w.write_all (&[2])?; Self::write_mac_opt (w, *mac)?; }, } Ok (()) } fn write_mac_opt (w: &mut W, mac: Option <[u8; 6]>) -> Result <(), std::io::Error> { match mac { Some (mac) => { w.write_all (&[1])?; w.write_all (&mac[..])?; }, None => w.write_all (&[0])?, } Ok (()) } pub fn to_vec (&self) -> Result , tlv::TlvError> { let mut cursor = Cursor::new (Vec::with_capacity (PACKET_SIZE)); self.write (&mut cursor)?; Ok (cursor.into_inner ()) } pub fn read (r: &mut R) -> Result { tlv::Reader::expect (r, &MAGIC_NUMBER)?; let t = tlv::Reader::u8 (r)?; Ok (match t { 1 => { let mut idem_id = [0u8; 8]; r.read_exact (&mut idem_id)?; let mac = Self::read_mac_opt (r)?; Self::Request { idem_id, mac, } }, 2 => { let mac = Self::read_mac_opt (r)?; Self::Response (mac) }, _ => return Err (MessageError::UnknownType), }) } fn read_mac_opt (r: &mut R) -> Result