#[derive(Debug, Clone)]
pub struct PacketEvent {
pub channel: String,
pub player: String,
pub payload: Vec<u8>,
}
pub trait PacketField: Sized {
fn write_to(&self, buf: &mut Vec<u8>);
fn read_from(buf: &[u8], pos: &mut usize) -> Option<Self>;
}
macro_rules! impl_fixed {
($T:ty, $N:literal) => {
impl PacketField for $T {
fn write_to(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(&self.to_le_bytes());
}
fn read_from(buf: &[u8], pos: &mut usize) -> Option<Self> {
let end = pos.checked_add($N)?;
if end > buf.len() { return None; }
let v = Self::from_le_bytes(buf[*pos..end].try_into().ok()?);
*pos = end;
Some(v)
}
}
};
}
impl_fixed!(i32, 4);
impl_fixed!(i64, 8);
impl_fixed!(u32, 4);
impl_fixed!(u64, 8);
impl_fixed!(f32, 4);
impl_fixed!(f64, 8);
impl PacketField for bool {
fn write_to(&self, buf: &mut Vec<u8>) { buf.push(*self as u8); }
fn read_from(buf: &[u8], pos: &mut usize) -> Option<Self> {
let b = *buf.get(*pos)?;
*pos += 1;
Some(b != 0)
}
}
impl PacketField for String {
fn write_to(&self, buf: &mut Vec<u8>) {
let bytes = self.as_bytes();
(bytes.len() as u32).write_to(buf);
buf.extend_from_slice(bytes);
}
fn read_from(buf: &[u8], pos: &mut usize) -> Option<Self> {
let len = u32::read_from(buf, pos)? as usize;
let end = pos.checked_add(len)?;
if end > buf.len() { return None; }
let s = std::str::from_utf8(&buf[*pos..end]).ok()?.to_owned();
*pos = end;
Some(s)
}
}
impl PacketField for Vec<u8> {
fn write_to(&self, buf: &mut Vec<u8>) {
(self.len() as u32).write_to(buf);
buf.extend_from_slice(self);
}
fn read_from(buf: &[u8], pos: &mut usize) -> Option<Self> {
let len = u32::read_from(buf, pos)? as usize;
let end = pos.checked_add(len)?;
if end > buf.len() { return None; }
let v = buf[*pos..end].to_vec();
*pos = end;
Some(v)
}
}
pub trait Packet: Sized {
fn encode(&self) -> Vec<u8>;
fn decode(bytes: &[u8]) -> Option<Self>;
}
#[macro_export]
macro_rules! packet {
(
$(#[$meta:meta])*
$vis:vis struct $Name:ident {
$( $fvis:vis $field:ident : $ty:ty ),* $(,)?
}
) => {
$(#[$meta])*
$vis struct $Name {
$( $fvis $field : $ty, )*
}
impl $crate::Packet for $Name {
fn encode(&self) -> ::std::vec::Vec<u8> {
let mut buf = ::std::vec::Vec::new();
$( $crate::PacketField::write_to(&self.$field, &mut buf); )*
buf
}
fn decode(bytes: &[u8]) -> ::std::option::Option<Self> {
let mut pos = 0usize;
$(
let $field = <$ty as $crate::PacketField>::read_from(bytes, &mut pos)?;
)*
::std::option::Option::Some(Self { $( $field, )* })
}
}
};
}