Skip to main content

blocky_net/
decoder.rs

1use std::io::{Cursor, Read};
2
3use crate::types::VarInt;
4
5pub trait Decoder {
6    fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self>
7    where
8        Self: Sized;
9
10    fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self>
11    where
12        Self: Sized,
13    {
14        let mut cursor = Cursor::new(bytes);
15        Self::decode(&mut cursor)
16    }
17}
18
19impl Decoder for bool {
20    fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self> {
21        let mut byte = [0];
22        buf.read_exact(&mut byte)?;
23        let byte = byte[0];
24
25        match byte {
26            0 => Ok(false),
27            1 => Ok(true),
28            _ => anyhow::bail!("Invalid boolean value"),
29        }
30    }
31}
32
33impl Decoder for String {
34    fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self> {
35        let length = VarInt::decode(buf)?.0 as usize;
36
37        let max_length = i16::MAX as usize;
38        if length > max_length {
39            anyhow::bail!(
40                "String length {} exceeds maximum allowed length of {}",
41                length,
42                max_length
43            );
44        }
45
46        let mut bytes = vec![0; length];
47        buf.read_exact(&mut bytes)?;
48
49        let s = std::str::from_utf8(&bytes)?;
50        Ok(s.to_string())
51    }
52}
53
54macro_rules! impl_number_decoder {
55    ($typ:ty) => {
56        impl Decoder for $typ {
57            fn decode<T: Read>(buf: &mut T) -> anyhow::Result<Self> {
58                let mut bytes = [0; std::mem::size_of::<Self>()];
59                buf.read_exact(&mut bytes)?;
60                Ok(Self::from_be_bytes(bytes))
61            }
62        }
63    };
64}
65
66impl_number_decoder!(u8);
67impl_number_decoder!(u16);
68impl_number_decoder!(u32);
69impl_number_decoder!(u64);
70impl_number_decoder!(u128);
71
72impl_number_decoder!(i8);
73impl_number_decoder!(i16);
74impl_number_decoder!(i32);
75impl_number_decoder!(i64);
76impl_number_decoder!(i128);
77
78impl_number_decoder!(f32);
79impl_number_decoder!(f64);