// namespacing use crate::Result; use async_std::net::TcpStream; use async_std::prelude::*; use futures_util::io::ReadHalf; use std::convert::TryInto; mod join; pub use join::Join; mod message; pub use message::Message; /// structured [packet type byte][four bytes of packet length][contents of packet] pub struct NetworkPacket(Vec); impl std::convert::Into for Packet { fn into(self) -> NetworkPacket { let mut contents: Vec = Vec::new(); // packet type byte contents.push(self.packet_type as u8); // write the packet length let contents_length = self.packet_contents.len() as u32; contents.extend_from_slice(&contents_length.to_le_bytes()); // write the rest of the contents contents.extend_from_slice(&self.packet_contents); NetworkPacket(contents) } } pub trait Sendable { fn to_packet(self) -> Packet; fn from_packet(packet: Packet) -> Self; } /// contains data to be turned into a network packet or into a more specific packet pub struct Packet { pub packet_type: PacketType, packet_contents: Vec, } impl Packet { /// create a new packet pub fn new(packet_type: PacketType, packet_contents: Vec) -> Self { Self { packet_type, packet_contents } } /// read a packet from a tcpstream pub async fn read(stream: &mut ReadHalf) -> Result> { let mut info_buf = [0u8; 5]; let check = stream.read(&mut info_buf).await?; if check == 0 { return Ok(None); } let packet_type = PacketType::from_u8(info_buf[0]).unwrap(); let length = u32::from_le_bytes(info_buf[1..5].try_into().unwrap()) as usize; let mut contents: Vec = vec![0; length]; stream.read(&mut contents).await?; Ok(Some(Packet::new(packet_type, contents))) } /// write a packet to the tcpstream pub async fn write(self, stream: &mut TcpStream) -> Result<()> { let network_packet: NetworkPacket = self.into(); stream.write(&network_packet.0).await?; Ok(()) } } /// represent the specific packet type #[repr(u8)] pub enum PacketType { Message = 0, Join = 1, } impl PacketType { /// returns the PacketType if the u8 is a valid packet type pub fn from_u8(packet_type: u8) -> Option { match packet_type { 0 => Some(Self::Message), _ => None, } } }