azalea_buf/
read.rs

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