azalea_buf/
read.rs

1use std::{
2    backtrace::Backtrace,
3    collections::HashMap,
4    hash::Hash,
5    io::{Cursor, Read},
6    sync::Arc,
7};
8
9use byteorder::{BE, ReadBytesExt};
10use thiserror::Error;
11use tracing::warn;
12
13use super::{MAX_STRING_LENGTH, UnsizedByteArray};
14
15#[derive(Error, Debug)]
16pub enum BufReadError {
17    #[error("Invalid VarInt")]
18    InvalidVarInt,
19    #[error("Invalid VarLong")]
20    InvalidVarLong,
21    #[error("Error reading bytes")]
22    CouldNotReadBytes,
23    #[error(
24        "The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})"
25    )]
26    StringLengthTooLong { length: u32, max_length: u32 },
27    #[error("The received Vec length is longer than maximum allowed ({length} > {max_length})")]
28    VecLengthTooLong { length: u32, max_length: u32 },
29    #[error("{source}")]
30    Io {
31        #[from]
32        #[backtrace]
33        source: std::io::Error,
34    },
35    #[error("Invalid UTF-8: {bytes:?} (lossy: {lossy:?})")]
36    InvalidUtf8 {
37        bytes: Vec<u8>,
38        lossy: String,
39        // backtrace: Backtrace,
40    },
41    #[error("Unexpected enum variant {id}")]
42    UnexpectedEnumVariant { id: i32 },
43    #[error("Unexpected enum variant {id}")]
44    UnexpectedStringEnumVariant { id: String },
45    #[error("Tried to read {attempted_read} bytes but there were only {actual_read}")]
46    UnexpectedEof {
47        attempted_read: usize,
48        actual_read: usize,
49        backtrace: Backtrace,
50    },
51    #[error("{0}")]
52    Custom(String),
53    #[cfg(feature = "serde_json")]
54    #[error("{source}")]
55    Deserialization {
56        #[from]
57        #[backtrace]
58        source: serde_json::Error,
59    },
60    #[error("{source}")]
61    Nbt {
62        #[from]
63        #[backtrace]
64        source: simdnbt::Error,
65    },
66    #[error("{source}")]
67    DeserializeNbt {
68        #[from]
69        #[backtrace]
70        source: simdnbt::DeserializeError,
71    },
72}
73
74fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8], BufReadError> {
75    if length > (buf.get_ref().len() - buf.position() as usize) {
76        return Err(BufReadError::UnexpectedEof {
77            attempted_read: length,
78            actual_read: buf.get_ref().len() - buf.position() as usize,
79            backtrace: Backtrace::capture(),
80        });
81    }
82    let initial_position = buf.position() as usize;
83    buf.set_position(buf.position() + length as u64);
84    let data = &buf.get_ref()[initial_position..initial_position + length];
85    Ok(data)
86}
87
88fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result<String, BufReadError> {
89    let length = u32::azalea_read_var(buf)?;
90    // i don't know why it's multiplied by 4 but it's like that in mojang's code so
91    if length > max_length * 4 {
92        return Err(BufReadError::StringLengthTooLong {
93            length,
94            max_length: max_length * 4,
95        });
96    }
97
98    let buffer = read_bytes(buf, length as usize)?;
99    let string = std::str::from_utf8(buffer)
100        .map_err(|_| BufReadError::InvalidUtf8 {
101            bytes: buffer.to_vec(),
102            lossy: String::from_utf8_lossy(buffer).to_string(),
103            // backtrace: Backtrace::capture(),
104        })?
105        .to_string();
106    if string.len() > length as usize {
107        return Err(BufReadError::StringLengthTooLong { length, max_length });
108    }
109
110    Ok(string)
111}
112
113pub trait AzaleaRead
114where
115    Self: Sized,
116{
117    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>;
118}
119
120pub trait AzaleaReadVar
121where
122    Self: Sized,
123{
124    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>;
125}
126
127// note that there's no Write equivalent for this trait since we don't really
128// care if we're writing over the limit (and maybe we already know that the
129// server implementation accepts it)
130pub trait AzaleaReadLimited
131where
132    Self: Sized,
133{
134    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError>;
135}
136
137impl AzaleaRead for i32 {
138    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
139        Ok(buf.read_i32::<BE>()?)
140    }
141}
142
143impl AzaleaReadVar for i32 {
144    // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
145    /// Read a single varint from the reader and return the value
146    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
147        let mut buffer = [0];
148        let mut ans = 0;
149        for i in 0..5 {
150            buf.read_exact(&mut buffer)?;
151            ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i);
152            if buffer[0] & 0b1000_0000 == 0 {
153                break;
154            }
155        }
156        Ok(ans)
157    }
158}
159
160impl AzaleaReadVar for i64 {
161    // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L54
162    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
163        let mut buffer = [0];
164        let mut ans = 0;
165        for i in 0..10 {
166            buf.read_exact(&mut buffer)
167                .map_err(|_| BufReadError::InvalidVarLong)?;
168            ans |= ((buffer[0] & 0b0111_1111) as i64) << (7 * i);
169            if buffer[0] & 0b1000_0000 == 0 {
170                break;
171            }
172        }
173        Ok(ans)
174    }
175}
176impl AzaleaReadVar for u64 {
177    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
178        i64::azalea_read_var(buf).map(|i| i as u64)
179    }
180}
181
182impl AzaleaRead for UnsizedByteArray {
183    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
184        // read to end of the buffer
185        let data = buf.get_ref()[buf.position() as usize..].to_vec();
186        buf.set_position((buf.position()) + data.len() as u64);
187        Ok(UnsizedByteArray(data))
188    }
189}
190
191impl<T: AzaleaRead> AzaleaRead for Vec<T> {
192    default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
193        let length = u32::azalea_read_var(buf)? as usize;
194        // we limit the capacity to not get exploited into allocating a bunch
195        let mut contents = Vec::with_capacity(usize::min(length, 65536));
196        for _ in 0..length {
197            contents.push(T::azalea_read(buf)?);
198        }
199        Ok(contents)
200    }
201}
202impl<T: AzaleaRead> AzaleaRead for Box<[T]> {
203    default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
204        Vec::<T>::azalea_read(buf).map(Vec::into_boxed_slice)
205    }
206}
207impl<T: AzaleaRead> AzaleaReadLimited for Vec<T> {
208    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
209        let length = u32::azalea_read_var(buf)? as usize;
210        if length > limit {
211            return Err(BufReadError::VecLengthTooLong {
212                length: length as u32,
213                max_length: limit as u32,
214            });
215        }
216
217        let mut contents = Vec::with_capacity(usize::min(length, 65536));
218        for _ in 0..length {
219            contents.push(T::azalea_read(buf)?);
220        }
221        Ok(contents)
222    }
223}
224impl<T: AzaleaRead> AzaleaReadLimited for Box<[T]> {
225    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
226        Vec::<T>::azalea_read_limited(buf, limit).map(Vec::into_boxed_slice)
227    }
228}
229
230impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaRead + Send> AzaleaRead for HashMap<K, V> {
231    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
232        let length = i32::azalea_read_var(buf)? as usize;
233        let mut contents = HashMap::with_capacity(usize::min(length, 65536));
234        for _ in 0..length {
235            contents.insert(K::azalea_read(buf)?, V::azalea_read(buf)?);
236        }
237        Ok(contents)
238    }
239}
240
241impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaReadVar + Send> AzaleaReadVar for HashMap<K, V> {
242    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
243        let length = i32::azalea_read_var(buf)? as usize;
244        let mut contents = HashMap::with_capacity(usize::min(length, 65536));
245        for _ in 0..length {
246            contents.insert(K::azalea_read(buf)?, V::azalea_read_var(buf)?);
247        }
248        Ok(contents)
249    }
250}
251
252impl AzaleaRead for Vec<u8> {
253    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
254        let length = i32::azalea_read_var(buf)? as usize;
255        read_bytes(buf, length).map(|b| b.to_vec())
256    }
257}
258
259impl AzaleaRead for String {
260    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
261        read_utf_with_len(buf, MAX_STRING_LENGTH.into())
262    }
263}
264impl AzaleaReadLimited for String {
265    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
266        read_utf_with_len(buf, limit as u32)
267    }
268}
269
270impl AzaleaRead for u32 {
271    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
272        Ok(i32::azalea_read(buf)? as u32)
273    }
274}
275
276impl AzaleaReadVar for u32 {
277    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
278        Ok(i32::azalea_read_var(buf)? as u32)
279    }
280}
281
282impl AzaleaRead for u16 {
283    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
284        i16::azalea_read(buf).map(|i| i as u16)
285    }
286}
287
288impl AzaleaRead for i16 {
289    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
290        Ok(buf.read_i16::<BE>()?)
291    }
292}
293
294impl AzaleaReadVar for u16 {
295    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
296        Ok(i32::azalea_read_var(buf)? as u16)
297    }
298}
299
300impl<T: AzaleaReadVar> AzaleaReadVar for Vec<T> {
301    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
302        let length = i32::azalea_read_var(buf)? as usize;
303        let mut contents = Vec::with_capacity(usize::min(length, 65536));
304        for _ in 0..length {
305            contents.push(T::azalea_read_var(buf)?);
306        }
307        Ok(contents)
308    }
309}
310impl<T: AzaleaReadVar> AzaleaReadVar for Box<[T]> {
311    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
312        Vec::<T>::azalea_read_var(buf).map(Vec::into_boxed_slice)
313    }
314}
315
316impl AzaleaRead for i64 {
317    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
318        Ok(buf.read_i64::<BE>()?)
319    }
320}
321
322impl AzaleaRead for u64 {
323    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
324        i64::azalea_read(buf).map(|i| i as u64)
325    }
326}
327
328impl AzaleaRead for bool {
329    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
330        let byte = u8::azalea_read(buf)?;
331        if byte > 1 {
332            warn!("Boolean value was not 0 or 1, but {}", byte);
333        }
334        Ok(byte != 0)
335    }
336}
337
338impl AzaleaRead for u8 {
339    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
340        Ok(buf.read_u8()?)
341    }
342}
343
344impl AzaleaRead for i8 {
345    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
346        u8::azalea_read(buf).map(|i| i as i8)
347    }
348}
349
350impl AzaleaRead for f32 {
351    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
352        Ok(buf.read_f32::<BE>()?)
353    }
354}
355
356impl AzaleaRead for f64 {
357    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
358        Ok(buf.read_f64::<BE>()?)
359    }
360}
361
362impl<T: AzaleaRead> AzaleaRead for Option<T> {
363    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
364        let present = bool::azalea_read(buf)?;
365        Ok(if present {
366            Some(T::azalea_read(buf)?)
367        } else {
368            None
369        })
370    }
371}
372
373impl<T: AzaleaReadVar> AzaleaReadVar for Option<T> {
374    fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
375        let present = bool::azalea_read(buf)?;
376        Ok(if present {
377            Some(T::azalea_read_var(buf)?)
378        } else {
379            None
380        })
381    }
382}
383impl<T: AzaleaReadLimited> AzaleaReadLimited for Option<T> {
384    fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
385        let present = bool::azalea_read(buf)?;
386        Ok(if present {
387            Some(T::azalea_read_limited(buf, limit)?)
388        } else {
389            None
390        })
391    }
392}
393
394// [String; 4]
395impl<T: AzaleaRead, const N: usize> AzaleaRead for [T; N] {
396    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
397        let mut contents = Vec::with_capacity(N);
398        for _ in 0..N {
399            contents.push(T::azalea_read(buf)?);
400        }
401        contents.try_into().map_err(|_| {
402            unreachable!("Panic is not possible since the Vec is the same size as the array")
403        })
404    }
405}
406
407impl AzaleaRead for simdnbt::owned::NbtTag {
408    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
409        Ok(simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)?)
410    }
411}
412
413impl AzaleaRead for simdnbt::owned::NbtCompound {
414    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
415        match simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)? {
416            simdnbt::owned::NbtTag::Compound(compound) => Ok(compound),
417            _ => Err(BufReadError::Custom("Expected compound tag".to_string())),
418        }
419    }
420}
421
422impl AzaleaRead for simdnbt::owned::Nbt {
423    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
424        Ok(simdnbt::owned::read_unnamed(buf)?)
425    }
426}
427
428impl<T> AzaleaRead for Box<T>
429where
430    T: AzaleaRead,
431{
432    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
433        Ok(Box::new(T::azalea_read(buf)?))
434    }
435}
436
437impl<A: AzaleaRead, B: AzaleaRead> AzaleaRead for (A, B) {
438    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
439        Ok((A::azalea_read(buf)?, B::azalea_read(buf)?))
440    }
441}
442
443impl<T: AzaleaRead> AzaleaRead for Arc<T> {
444    fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
445        Ok(Arc::new(T::azalea_read(buf)?))
446    }
447}