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