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::{Cursor, Read};

use crate::types::VarInt;

pub trait Decoder {
    fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self>
    where
        Self: Sized;

    fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
    where
        Self: Sized,
    {
        let mut cursor = Cursor::new(bytes);
        Self::decode(&mut cursor)
    }
}

impl Decoder for bool {
    fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self> {
        let mut byte = [0];
        buf.read_exact(&mut byte)?;
        let byte = byte[0];

        match byte {
            0 => Ok(false),
            1 => Ok(true),
            _ => anyhow::bail!("Invalid boolean value"),
        }
    }
}

impl Decoder for String {
    fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self> {
        let length = VarInt::decode(buf)?.0 as usize;

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

        let mut bytes = vec![0; length];
        buf.read_exact(&mut bytes)?;

        let s = std::str::from_utf8(&bytes)?;
        Ok(s.to_string())
    }
}

macro_rules! impl_number_decoder {
    ($typ:ty) => {
        impl Decoder for $typ {
            fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self> {
                let mut bytes = [0; std::mem::size_of::<Self>()];
                buf.read_exact(&mut bytes)?;
                Ok(Self::from_be_bytes(bytes))
            }
        }
    };
}

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

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

impl_number_decoder!(f32);
impl_number_decoder!(f64);