blocky-net 0.2.0

A Rust library for creating Minecraft clients, enabling packet manipulation and automated interactions with Minecraft servers.
Documentation
use std::io::Write;

use crate::types::VarInt;

pub trait Encoder {
    fn byte_len(&self) -> usize
    where
        Self: Sized;

    fn encode<T: Write>(&self, buf: &mut T) -> anyhow::Result<()>
    where
        Self: Sized;

    fn to_bytes(&self) -> anyhow::Result<Vec<u8>>
    where
        Self: Sized,
    {
        let mut buf = Vec::with_capacity(self.byte_len());
        self.encode(&mut buf)?;
        Ok(buf)
    }
}

impl Encoder for bool {
    fn byte_len(&self) -> usize {
        1
    }

    fn encode<T: Write>(&self, buf: &mut T) -> anyhow::Result<()> {
        buf.write_all(&[*self as u8])?;
        Ok(())
    }
}

impl Encoder for String {
    fn byte_len(&self) -> usize {
        VarInt(self.len() as i32).byte_len() + self.len()
    }

    fn encode<T: Write>(&self, buf: &mut T) -> anyhow::Result<()> {
        let length = self.len();

        let max_length = i16::MAX as usize;
        if length > max_length {
            anyhow::bail!(
                "String length {} exceeds maximum allowed length of {}",
                length,
                max_length
            );
        }

        VarInt(length as i32).encode(buf)?;
        buf.write_all(&self.to_bytes()?)?;
        Ok(())
    }
}

macro_rules! impl_number_encoder {
    ($typ:ty) => {
        impl Encoder for $typ {
            fn byte_len(&self) -> usize {
                std::mem::size_of::<Self>()
            }

            fn encode<T: Write>(&self, buf: &mut T) -> anyhow::Result<()> {
                buf.write_all(&self.to_be_bytes())?;
                Ok(())
            }
        }
    };
}

impl_number_encoder!(u8);
impl_number_encoder!(u16);
impl_number_encoder!(u32);
impl_number_encoder!(u64);
impl_number_encoder!(u128);

impl_number_encoder!(i8);
impl_number_encoder!(i16);
impl_number_encoder!(i32);
impl_number_encoder!(i64);
impl_number_encoder!(i128);

impl_number_encoder!(f32);
impl_number_encoder!(f64);