rust-server/src/packets/mod.rs

96 lines
2.1 KiB
Rust

use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use anyhow::Result;
use uuid::Uuid;
pub mod clientbound;
pub mod serverbound;
pub trait Decode: Sized {
fn decode(cursor: &mut Cursor<&[u8]>) -> Result<Self>;
}
pub trait Encode: Sized {
fn encode(&self, buffer: &mut Vec<u8>) -> Result<()>;
}
pub trait Packet: Decode + Encode {
fn get_id(&self) -> i32;
}
impl <T> Encode for Option<T>
where T: Encode {
fn encode(&self, buffer: &mut Vec<u8>) -> Result<()> {
match self {
Some(it) => it.encode(buffer),
None => Ok(())
}
}
}
macro_rules! number_impl {
($($type:ty, $read_fn:tt, $write_fn:tt),* $(,)?) => {
$(
impl Decode for $type {
fn decode(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
cursor.$read_fn::<BigEndian>().map_err(anyhow::Error::from)
}
}
impl Encode for $type {
fn encode(&self, buffer: &mut Vec<u8>) -> Result<()> {
buffer.$write_fn::<BigEndian>(*self).map_err(anyhow::Error::from)
}
}
)*
}
}
number_impl! {
u16, read_u16, write_u16,
u32, read_u32, write_u32,
u64, read_u64, write_u64,
i16, read_i16, write_i16,
i32, read_i32, write_i32,
i64, read_i64, write_i64,
f32, read_f32, write_f32,
f64, read_f64, write_f64,
}
impl Decode for bool {
fn decode(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
let data = cursor.read_u8()?;
Ok(data != 0x00)
}
}
impl Encode for bool {
fn encode(&self, buffer: &mut Vec<u8>) -> Result<()> {
if *self {
buffer.push(0x01);
} else {
buffer.push(0x00);
}
Ok(())
}
}
impl Decode for Uuid {
fn decode(cursor: &mut Cursor<&[u8]>) -> Result<Self> {
let data = cursor.read_u128::<BigEndian>()?;
Ok(Uuid::from_u128(data))
}
}
impl Encode for Uuid {
fn encode(&self, buffer: &mut Vec<u8>) -> Result<()> {
buffer.write_u128::<BigEndian>(self.as_u128())?;
Ok(())
}
}