From cfb190d00c70f1b09789e23f89a3c67840e0fd87 Mon Sep 17 00:00:00 2001 From: mat <27899617+mat-1@users.noreply.github.com> Date: Fri, 2 Sep 2022 12:11:14 -0500 Subject: get rid of Readable & Writable (#21) --- azalea-buf/src/read.rs | 235 +++++++++++++------------------------------------ 1 file changed, 60 insertions(+), 175 deletions(-) (limited to 'azalea-buf/src/read.rs') diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs index a7ebc10c..82fd4f2f 100644 --- a/azalea-buf/src/read.rs +++ b/azalea-buf/src/read.rs @@ -12,14 +12,10 @@ pub enum BufReadError { InvalidVarLong, #[error("Error reading bytes")] CouldNotReadBytes, - #[error("The received encoded string buffer length is less than zero! Weird string!")] - StringLengthLessThanZero, #[error("The received encoded string buffer length is longer than maximum allowed ({length} > {max_length})")] - StringLengthTooLong { length: i32, max_length: u32 }, + StringLengthTooLong { length: u32, max_length: u32 }, #[error("{0}")] Io(#[from] std::io::Error), - #[error("Boolean value is not 0 or 1")] - InvalidBoolean, #[error("Invalid UTF-8")] InvalidUtf8, #[error("Unexpected enum variant {id}")] @@ -33,158 +29,27 @@ pub enum BufReadError { Deserialization(#[from] serde_json::Error), } -// TODO: get rid of Readable and use McBufReadable everywhere - -pub trait Readable { - fn read_int_id_list(&mut self) -> Result, BufReadError>; - fn read_varint(&mut self) -> Result; - fn get_varint_size(&mut self, value: i32) -> u8; - fn get_varlong_size(&mut self, value: i32) -> u8; - fn read_byte_array(&mut self) -> Result, BufReadError>; - fn read_bytes_with_len(&mut self, n: usize) -> Result, BufReadError>; - fn read_bytes(&mut self) -> Result, BufReadError>; - fn read_utf(&mut self) -> Result; - fn read_utf_with_len(&mut self, max_length: u32) -> Result; - fn read_byte(&mut self) -> Result; - fn read_int(&mut self) -> Result; - fn read_boolean(&mut self) -> Result; - fn read_long(&mut self) -> Result; - fn read_short(&mut self) -> Result; - fn read_float(&mut self) -> Result; - fn read_double(&mut self) -> Result; -} - -impl Readable for R -where - R: Read, -{ - fn read_int_id_list(&mut self) -> Result, BufReadError> { - let len = self.read_varint()?; - let mut list = Vec::with_capacity(len as usize); - for _ in 0..len { - list.push(self.read_varint()?); - } - Ok(list) +fn read_utf_with_len(buf: &mut impl Read, max_length: u32) -> Result { + let length = u32::var_read_from(buf)?; + // i don't know why it's multiplied by 4 but it's like that in mojang's code so + if length as u32 > max_length * 4 { + return Err(BufReadError::StringLengthTooLong { + length, + max_length: max_length * 4, + }); } - // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 - /// Read a single varint from the reader and return the value - fn read_varint(&mut self) -> Result { - let mut buffer = [0]; - let mut ans = 0; - for i in 0..5 { - self.read_exact(&mut buffer) - .map_err(|_| BufReadError::InvalidVarInt)?; - ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); - if buffer[0] & 0b1000_0000 == 0 { - break; - } - } - Ok(ans) + // this is probably quite inefficient, idk how to do it better + let mut string = String::new(); + let mut buffer = vec![0; length as usize]; + buf.read_exact(&mut buffer) + .map_err(|_| BufReadError::InvalidUtf8)?; + string.push_str(std::str::from_utf8(&buffer).unwrap()); + if string.len() > length as usize { + return Err(BufReadError::StringLengthTooLong { length, max_length }); } - fn get_varint_size(&mut self, value: i32) -> u8 { - for i in 1..5 { - if (value & -1 << (i * 7)) != 0 { - continue; - } - return i; - } - 5 - } - - fn get_varlong_size(&mut self, value: i32) -> u8 { - for i in 1..10 { - if (value & -1 << (i * 7)) != 0 { - continue; - } - return i; - } - 10 - } - - fn read_byte_array(&mut self) -> Result, BufReadError> { - let length = self.read_varint()? as usize; - self.read_bytes_with_len(length) - } - - fn read_bytes_with_len(&mut self, n: usize) -> Result, BufReadError> { - let mut buffer = vec![0; n]; - self.read_exact(&mut buffer) - .map_err(|_| BufReadError::CouldNotReadBytes)?; - Ok(buffer) - } - - fn read_bytes(&mut self) -> Result, BufReadError> { - // read to end of the buffer - let mut bytes = vec![]; - self.read_to_end(&mut bytes) - .map_err(|_| BufReadError::CouldNotReadBytes)?; - Ok(bytes) - } - - fn read_utf(&mut self) -> Result { - self.read_utf_with_len(MAX_STRING_LENGTH.into()) - } - - fn read_utf_with_len(&mut self, max_length: u32) -> Result { - let length = self.read_varint()?; - // i don't know why it's multiplied by 4 but it's like that in mojang's code so - if length < 0 { - return Err(BufReadError::StringLengthLessThanZero); - } - if length as u32 > max_length * 4 { - return Err(BufReadError::StringLengthTooLong { - length, - max_length: max_length * 4, - }); - } - - // this is probably quite inefficient, idk how to do it better - let mut string = String::new(); - let mut buffer = vec![0; length as usize]; - self.read_exact(&mut buffer) - .map_err(|_| BufReadError::InvalidUtf8)?; - string.push_str(std::str::from_utf8(&buffer).unwrap()); - if string.len() > length as usize { - return Err(BufReadError::StringLengthTooLong { length, max_length }); - } - - Ok(string) - } - - /// Read a single byte from the reader - fn read_byte(&mut self) -> Result { - Ok(self.read_u8()?) - } - - fn read_int(&mut self) -> Result { - Ok(self.read_i32::()?) - } - - fn read_boolean(&mut self) -> Result { - match self.read_byte()? { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(BufReadError::InvalidBoolean), - } - } - - fn read_long(&mut self) -> Result { - Ok(self.read_i64::()?) - } - - fn read_short(&mut self) -> Result { - Ok(self.read_i16::()?) - } - - fn read_float(&mut self) -> Result { - Ok(self.read_f32::()?) - } - - fn read_double(&mut self) -> Result { - Ok(self.read_f64::()?) - } + Ok(string) } // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 @@ -223,13 +88,25 @@ where impl McBufReadable for i32 { fn read_from(buf: &mut impl Read) -> Result { - Readable::read_int(buf) + Ok(buf.read_i32::()?) } } impl McBufVarReadable for i32 { + // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 + /// Read a single varint from the reader and return the value fn var_read_from(buf: &mut impl Read) -> Result { - buf.read_varint() + let mut buffer = [0]; + let mut ans = 0; + for i in 0..5 { + buf.read_exact(&mut buffer) + .map_err(|_| BufReadError::InvalidVarInt)?; + ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); + if buffer[0] & 0b1000_0000 == 0 { + break; + } + } + Ok(ans) } } @@ -257,13 +134,17 @@ impl McBufVarReadable for u64 { impl McBufReadable for UnsizedByteArray { fn read_from(buf: &mut impl Read) -> Result { - Ok(buf.read_bytes()?.into()) + // read to end of the buffer + let mut bytes = vec![]; + buf.read_to_end(&mut bytes) + .map_err(|_| BufReadError::CouldNotReadBytes)?; + Ok(bytes.into()) } } impl McBufReadable for Vec { default fn read_from(buf: &mut impl Read) -> Result { - let length = buf.read_varint()? as usize; + let length = u32::var_read_from(buf)? as usize; let mut contents = Vec::with_capacity(length); for _ in 0..length { contents.push(T::read_from(buf)?); @@ -274,7 +155,7 @@ impl McBufReadable for Vec { impl McBufReadable for HashMap { default fn read_from(buf: &mut impl Read) -> Result { - let length = buf.read_varint()? as usize; + let length = i32::var_read_from(buf)? as usize; let mut contents = HashMap::with_capacity(length); for _ in 0..length { contents.insert(K::read_from(buf)?, V::read_from(buf)?); @@ -287,7 +168,7 @@ impl McBufVarRe for HashMap { default fn var_read_from(buf: &mut impl Read) -> Result { - let length = buf.read_varint()? as usize; + let length = i32::var_read_from(buf)? as usize; let mut contents = HashMap::with_capacity(length); for _ in 0..length { contents.insert(K::read_from(buf)?, V::var_read_from(buf)?); @@ -298,49 +179,53 @@ impl McBufVarRe impl McBufReadable for Vec { fn read_from(buf: &mut impl Read) -> Result { - buf.read_byte_array() + let length = i32::var_read_from(buf)? as usize; + let mut buffer = vec![0; length]; + buf.read_exact(&mut buffer) + .map_err(|_| BufReadError::CouldNotReadBytes)?; + Ok(buffer) } } impl McBufReadable for String { fn read_from(buf: &mut impl Read) -> Result { - buf.read_utf() + read_utf_with_len(buf, MAX_STRING_LENGTH.into()) } } impl McBufReadable for u32 { fn read_from(buf: &mut impl Read) -> Result { - Readable::read_int(buf).map(|i| i as u32) + Ok(i32::read_from(buf)? as u32) } } impl McBufVarReadable for u32 { fn var_read_from(buf: &mut impl Read) -> Result { - buf.read_varint().map(|i| i as u32) + Ok(i32::var_read_from(buf)? as u32) } } impl McBufReadable for u16 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_short().map(|i| i as u16) + i32::read_from(buf).map(|i| i as u16) } } impl McBufReadable for i16 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_short() + Ok(buf.read_i16::()?) } } impl McBufVarReadable for u16 { fn var_read_from(buf: &mut impl Read) -> Result { - buf.read_varint().map(|i| i as u16) + Ok(i32::var_read_from(buf)? as u16) } } impl McBufVarReadable for Vec { fn var_read_from(buf: &mut impl Read) -> Result { - let length = buf.read_varint()? as usize; + let length = i32::var_read_from(buf)? as usize; let mut contents = Vec::with_capacity(length); for _ in 0..length { contents.push(T::var_read_from(buf)?); @@ -351,7 +236,7 @@ impl McBufVarReadable for Vec { impl McBufReadable for i64 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_long() + Ok(buf.read_i64::()?) } } @@ -363,37 +248,37 @@ impl McBufReadable for u64 { impl McBufReadable for bool { fn read_from(buf: &mut impl Read) -> Result { - buf.read_boolean() + Ok(u8::read_from(buf)? != 0) } } impl McBufReadable for u8 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_byte() + Ok(buf.read_u8()?) } } impl McBufReadable for i8 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_byte().map(|i| i as i8) + u8::read_from(buf).map(|i| i as i8) } } impl McBufReadable for f32 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_float() + Ok(buf.read_f32::()?) } } impl McBufReadable for f64 { fn read_from(buf: &mut impl Read) -> Result { - buf.read_double() + Ok(buf.read_f64::()?) } } impl McBufReadable for Option { default fn read_from(buf: &mut impl Read) -> Result { - let present = buf.read_boolean()?; + let present = bool::read_from(buf)?; Ok(if present { Some(T::read_from(buf)?) } else { @@ -404,7 +289,7 @@ impl McBufReadable for Option { impl McBufVarReadable for Option { default fn var_read_from(buf: &mut impl Read) -> Result { - let present = buf.read_boolean()?; + let present = bool::read_from(buf)?; Ok(if present { Some(T::var_read_from(buf)?) } else { -- cgit v1.2.3