use bincode::{Encode, Decode}; use std::error::Error; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; use tracing::{debug, error}; use crate::packet_type::PacketType; #[derive(Debug)] pub struct Packet { pub packet_size: u16, pub packet_type: PacketType, pub packet_crc: u16, pub payload: Vec, } pub trait PacketPayload: Encode + Decode { fn encode(&self) -> Result, Box> { let config = bincode::config::standard() .with_fixed_int_encoding(); Ok(bincode::encode_to_vec(self, config)?) } fn decode(data: &[u8]) -> Result> where Self: Sized, { let config = bincode::config::standard() .with_fixed_int_encoding(); Ok(bincode::decode_from_slice(data, config)?.0) } } impl Packet { pub fn new(packet_type: PacketType, payload: &T) -> Result> { let encoded_payload = ::encode(payload)?; let packet_size = (6 + encoded_payload.len()) as u16; // let packet_crc = crc::crc16::checksum_x25(&encoded_payload); let packet_crc = 0; Ok(Self { packet_size, packet_type, packet_crc, payload: encoded_payload, }) } pub fn from_raw(data: &[u8]) -> Result> { if data.len() < 6 { return Err("Invalid packet: Too short".into()); } // Extract packet fields let packet_size = u16::from_le_bytes(data[0..2].try_into()?); let raw_packet_type = u16::from_le_bytes(data[2..4].try_into()?); let packet_crc = u16::from_le_bytes(data[4..6].try_into()?); // Validate the size if packet_size as usize != data.len() { error!("Invalid packet: Size mismatch, expected: {}, actual: {}", packet_size, data.len()); return Err("Invalid packet: Size mismatch".into()); } debug!("size: {:#X}, raw_type: {:#X}, crc: {:#X}", packet_size, raw_packet_type, packet_crc); // Convert raw packet type into `PacketType` enum let packet_type = PacketType::try_from(raw_packet_type)?; // Extract the payload let payload = data[6..].to_vec(); Ok(Self { packet_size, packet_type, packet_crc, payload, }) } /// Serialize the `Packet` back to raw bytes pub fn to_raw(&self) -> Vec { let mut raw = Vec::with_capacity(self.packet_size as usize); // Serialize fields raw.extend(&self.packet_size.to_le_bytes()); raw.extend(&(self.packet_type as u16).to_le_bytes()); raw.extend(&self.packet_crc.to_le_bytes()); raw.extend(&self.payload); raw } pub fn parse(&self) -> Result> { ::decode(&self.payload) } } pub async fn send_packet(stream: &mut TcpStream, packet: &Packet) -> Result<(), std::io::Error> { let data = packet.to_raw(); debug!("Sending data: {:?}", data); stream.write_all(&data).await?; Ok(()) }