pub mod data_types; pub mod identifier; pub mod packet_data; use crate::prelude; use identifier::Identifier; use packet_data::PacketData; use std::convert::TryFrom; use std::fmt::Debug; use std::io::Read; #[derive(Debug)] pub enum Packet { V1 { src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier, command: u8, data: PacketData, }, } impl Packet { pub fn packet_id(&self) -> Identifier { match self { Packet::V1 { packet_id, .. } => packet_id.clone() } } pub fn command(&self) -> u8 { match self { Packet::V1 { command, .. } => command.clone() } } pub fn data(&self) -> PacketData { match self { Packet::V1 { data, .. } => data.clone() } } /// Build packet **without** CRC32 pub fn build_base_packet(&self) -> Vec { match self { Packet::V1 { src, dest, packet_id, reply_to, command, data, } => { let mut buf = Vec::new(); let data_length = data.len(); buf.push(0x01); buf.extend_from_slice(&src.bytes); buf.extend_from_slice(&dest.bytes); buf.extend_from_slice(&packet_id.bytes); buf.extend_from_slice(&reply_to.bytes); buf.push(command.clone()); buf.push((data_length >> 8) as u8); buf.push((data_length & 0xFF) as u8); buf.extend(data.get_data()); buf } } } pub fn build_full_packet(&self) -> Vec { match self { Packet::V1 { .. } => { let mut buf = self.build_base_packet(); buf.extend_from_slice(crc32fast::hash(&buf.as_slice()).to_be_bytes().as_ref()); buf } } } } impl TryFrom> for Packet { type Error = (); fn try_from(value: Vec) -> Result { match value[0] { 0x01 => { let header: Vec = value[..0x15].iter().map(|v| u16::from(*v)).collect(); let data_length = (header[0x12] << 8) | header[0x13]; let crc32 = prelude::as_u32_be(&value[(0x14 + data_length as usize)..]); let packet = Packet::V1 { src: Identifier::from(&value[0x01..0x05]), dest: Identifier::from(&value[0x05..0x09]), packet_id: Identifier::from(&value[0x09..0x0D]), reply_to: Identifier::from(&value[0x0D..0x11]), command: value[0x11], data: PacketData::new(value[0x14..(data_length as usize + 0x14)].to_owned()), }; if crc32fast::hash(packet.build_base_packet().as_slice()) != crc32 { Err(()) } else { Ok(packet) } } _ => Err(()), } } } impl Into> for Packet { fn into(self) -> Vec { self.build_full_packet() } } pub trait ToPacket { fn to_v1_packet(self, src: Identifier, dest: Identifier, packet_id: Identifier, reply_to: Identifier) -> Packet; }