diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-09-02 12:11:14 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-02 12:11:14 -0500 |
| commit | cfb190d00c70f1b09789e23f89a3c67840e0fd87 (patch) | |
| tree | 9bdc021943753d60bf437526c4c294275eae13ac /azalea-buf | |
| parent | 32458d743f757da3193717fe5554f490703640c0 (diff) | |
| download | azalea-drasl-cfb190d00c70f1b09789e23f89a3c67840e0fd87.tar.xz | |
get rid of Readable & Writable (#21)
Diffstat (limited to 'azalea-buf')
| -rw-r--r-- | azalea-buf/README.md | 2 | ||||
| -rw-r--r-- | azalea-buf/azalea-buf-macros/src/lib.rs | 2 | ||||
| -rw-r--r-- | azalea-buf/src/lib.rs | 119 | ||||
| -rw-r--r-- | azalea-buf/src/read.rs | 235 | ||||
| -rw-r--r-- | azalea-buf/src/serializable_uuid.rs | 11 | ||||
| -rw-r--r-- | azalea-buf/src/write.rs | 180 |
6 files changed, 170 insertions, 379 deletions
diff --git a/azalea-buf/README.md b/azalea-buf/README.md index c988bcdb..cfb701ff 100644 --- a/azalea-buf/README.md +++ b/azalea-buf/README.md @@ -1,3 +1,5 @@ # Azalea Buf An implementation of Minecraft's FriendlyByteBuf. This is used frequently in the game for serialization and deserialization of data. + +Note that there are some minor implementation differences such as using unsigned integers in places where Minecraft uses signed integers. This doesn't cause issues normally, but does technically make usage of azalea-buf detectable if a server really wants to since it won't error in places where vanilla Minecraft would. diff --git a/azalea-buf/azalea-buf-macros/src/lib.rs b/azalea-buf/azalea-buf-macros/src/lib.rs index 43e60e6e..0d77488f 100644 --- a/azalea-buf/azalea-buf-macros/src/lib.rs +++ b/azalea-buf/azalea-buf-macros/src/lib.rs @@ -145,7 +145,7 @@ fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt quote! { impl azalea_buf::McBufWritable for #ident { fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> { - azalea_buf::Writable::write_varint(buf, *self as i32) + azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf) } } } diff --git a/azalea-buf/src/lib.rs b/azalea-buf/src/lib.rs index b8190dfb..24392f6e 100644 --- a/azalea-buf/src/lib.rs +++ b/azalea-buf/src/lib.rs @@ -9,9 +9,9 @@ mod write; pub use azalea_buf_macros::*; pub use definitions::*; -pub use read::{read_varint_async, BufReadError, McBufReadable, McBufVarReadable, Readable}; +pub use read::{read_varint_async, BufReadError, McBufReadable, McBufVarReadable}; pub use serializable_uuid::*; -pub use write::{McBufVarWritable, McBufWritable, Writable}; +pub use write::{McBufVarWritable, McBufWritable}; // const DEFAULT_NBT_QUOTA: u32 = 2097152; const MAX_STRING_LENGTH: u16 = 32767; @@ -20,173 +20,146 @@ const MAX_STRING_LENGTH: u16 = 32767; #[cfg(test)] mod tests { use super::*; - use std::io::Cursor; + use std::{collections::HashMap, io::Cursor}; #[test] fn test_write_varint() { let mut buf = Vec::new(); - buf.write_varint(0).unwrap(); + 0.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![0]); let mut buf = Vec::new(); - buf.write_varint(1).unwrap(); + 1.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![1]); let mut buf = Vec::new(); - buf.write_varint(2).unwrap(); + 2.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![2]); let mut buf = Vec::new(); - buf.write_varint(127).unwrap(); + 127.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![127]); let mut buf = Vec::new(); - buf.write_varint(128).unwrap(); + 128.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![128, 1]); let mut buf = Vec::new(); - buf.write_varint(255).unwrap(); + 255.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![255, 1]); let mut buf = Vec::new(); - buf.write_varint(25565).unwrap(); + 25565.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![221, 199, 1]); let mut buf = Vec::new(); - buf.write_varint(2097151).unwrap(); + 2097151.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![255, 255, 127]); let mut buf = Vec::new(); - buf.write_varint(2147483647).unwrap(); + 2147483647.var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![255, 255, 255, 255, 7]); let mut buf = Vec::new(); - buf.write_varint(-1).unwrap(); + (-1).var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![255, 255, 255, 255, 15]); let mut buf = Vec::new(); - buf.write_varint(-2147483648).unwrap(); + (-2147483648).var_write_into(&mut buf).unwrap(); assert_eq!(buf, vec![128, 128, 128, 128, 8]); } #[test] fn test_read_varint() { let mut buf = Cursor::new(vec![0]); - assert_eq!(buf.read_varint().unwrap(), 0); - assert_eq!(buf.get_varint_size(0), 1); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 0); let mut buf = Cursor::new(vec![1]); - assert_eq!(buf.read_varint().unwrap(), 1); - assert_eq!(buf.get_varint_size(1), 1); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 1); let mut buf = Cursor::new(vec![2]); - assert_eq!(buf.read_varint().unwrap(), 2); - assert_eq!(buf.get_varint_size(2), 1); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2); let mut buf = Cursor::new(vec![127]); - assert_eq!(buf.read_varint().unwrap(), 127); - assert_eq!(buf.get_varint_size(127), 1); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 127); let mut buf = Cursor::new(vec![128, 1]); - assert_eq!(buf.read_varint().unwrap(), 128); - assert_eq!(buf.get_varint_size(128), 2); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 128); let mut buf = Cursor::new(vec![255, 1]); - assert_eq!(buf.read_varint().unwrap(), 255); - assert_eq!(buf.get_varint_size(255), 2); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 255); let mut buf = Cursor::new(vec![221, 199, 1]); - assert_eq!(buf.read_varint().unwrap(), 25565); - assert_eq!(buf.get_varint_size(25565), 3); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 25565); let mut buf = Cursor::new(vec![255, 255, 127]); - assert_eq!(buf.read_varint().unwrap(), 2097151); - assert_eq!(buf.get_varint_size(2097151), 3); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2097151); let mut buf = Cursor::new(vec![255, 255, 255, 255, 7]); - assert_eq!(buf.read_varint().unwrap(), 2147483647); - assert_eq!(buf.get_varint_size(2147483647), 5); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2147483647); let mut buf = Cursor::new(vec![255, 255, 255, 255, 15]); - assert_eq!(buf.read_varint().unwrap(), -1); - assert_eq!(buf.get_varint_size(-1), 5); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), -1); let mut buf = Cursor::new(vec![128, 128, 128, 128, 8]); - assert_eq!(buf.read_varint().unwrap(), -2147483648); - assert_eq!(buf.get_varint_size(-2147483648), 5); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), -2147483648); } #[test] fn test_read_varint_longer() { let mut buf = Cursor::new(vec![138, 56, 0, 135, 56, 123]); - assert_eq!(buf.read_varint().unwrap(), 7178); + assert_eq!(i32::var_read_from(&mut buf).unwrap(), 7178); } #[test] fn test_list() { - let mut buf = Vec::new(); - buf.write_list(&vec!["a", "bc", "def"], |buf, s| buf.write_utf(s)) - .unwrap(); + let original_vec = vec!["a".to_string(), "bc".to_string(), "def".to_string()]; - // there's no read_list because idk how to do it in rust - let mut buf = Cursor::new(buf); + let mut buf = Vec::new(); + original_vec.write_into(&mut buf).unwrap(); - let mut result = Vec::new(); - let length = buf.read_varint().unwrap(); - for _ in 0..length { - result.push(buf.read_utf().unwrap()); - } + dbg!(&buf); - assert_eq!(result, vec!["a", "bc", "def"]); + let mut buf = Cursor::new(buf); + let result = Vec::<String>::read_from(&mut buf).unwrap(); + assert_eq!(result, original_vec); } #[test] fn test_int_id_list() { let mut buf = Vec::new(); - buf.write_list(&vec![1, 2, 3], |buf, i| buf.write_varint(*i)) - .unwrap(); + vec![1, 2, 3].var_write_into(&mut buf).unwrap(); let mut buf = Cursor::new(buf); - let result = buf.read_int_id_list().unwrap(); + let result = Vec::<i32>::var_read_from(&mut buf).unwrap(); assert_eq!(result, vec![1, 2, 3]); } #[test] fn test_map() { + let original_map = HashMap::from([ + ("a".to_string(), 1), + ("bc".to_string(), 23), + ("def".to_string(), 456), + ]); let mut buf = Vec::new(); - buf.write_map( - vec![("a", 1), ("bc", 23), ("def", 456)], - Vec::write_utf, - Vec::write_varint, - ) - .unwrap(); + original_map.var_write_into(&mut buf).unwrap(); let mut buf = Cursor::new(buf); - let mut result = Vec::new(); - let length = buf.read_varint().unwrap(); - for _ in 0..length { - result.push((buf.read_utf().unwrap(), buf.read_varint().unwrap())); - } - - assert_eq!( - result, - vec![ - ("a".to_string(), 1), - ("bc".to_string(), 23), - ("def".to_string(), 456) - ] - ); + let result = HashMap::<String, i32>::var_read_from(&mut buf).unwrap(); + + assert_eq!(result, original_map); } #[test] fn test_long() { let mut buf = Vec::new(); - buf.write_long(123456).unwrap(); + 123456u64.write_into(&mut buf).unwrap(); let mut buf = Cursor::new(buf); - assert_eq!(buf.read_long().unwrap(), 123456); + assert_eq!(u64::read_from(&mut buf).unwrap(), 123456); } } 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<Vec<i32>, BufReadError>; - fn read_varint(&mut self) -> Result<i32, BufReadError>; - 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<Vec<u8>, BufReadError>; - fn read_bytes_with_len(&mut self, n: usize) -> Result<Vec<u8>, BufReadError>; - fn read_bytes(&mut self) -> Result<Vec<u8>, BufReadError>; - fn read_utf(&mut self) -> Result<String, BufReadError>; - fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, BufReadError>; - fn read_byte(&mut self) -> Result<u8, BufReadError>; - fn read_int(&mut self) -> Result<i32, BufReadError>; - fn read_boolean(&mut self) -> Result<bool, BufReadError>; - fn read_long(&mut self) -> Result<i64, BufReadError>; - fn read_short(&mut self) -> Result<i16, BufReadError>; - fn read_float(&mut self) -> Result<f32, BufReadError>; - fn read_double(&mut self) -> Result<f64, BufReadError>; -} - -impl<R> Readable for R -where - R: Read, -{ - fn read_int_id_list(&mut self) -> Result<Vec<i32>, 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<String, BufReadError> { + 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<i32, BufReadError> { - 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<Vec<u8>, BufReadError> { - let length = self.read_varint()? as usize; - self.read_bytes_with_len(length) - } - - fn read_bytes_with_len(&mut self, n: usize) -> Result<Vec<u8>, BufReadError> { - let mut buffer = vec![0; n]; - self.read_exact(&mut buffer) - .map_err(|_| BufReadError::CouldNotReadBytes)?; - Ok(buffer) - } - - fn read_bytes(&mut self) -> Result<Vec<u8>, 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<String, BufReadError> { - self.read_utf_with_len(MAX_STRING_LENGTH.into()) - } - - fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, BufReadError> { - 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<u8, BufReadError> { - Ok(self.read_u8()?) - } - - fn read_int(&mut self) -> Result<i32, BufReadError> { - Ok(self.read_i32::<BE>()?) - } - - fn read_boolean(&mut self) -> Result<bool, BufReadError> { - match self.read_byte()? { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(BufReadError::InvalidBoolean), - } - } - - fn read_long(&mut self) -> Result<i64, BufReadError> { - Ok(self.read_i64::<BE>()?) - } - - fn read_short(&mut self) -> Result<i16, BufReadError> { - Ok(self.read_i16::<BE>()?) - } - - fn read_float(&mut self) -> Result<f32, BufReadError> { - Ok(self.read_f32::<BE>()?) - } - - fn read_double(&mut self) -> Result<f64, BufReadError> { - Ok(self.read_f64::<BE>()?) - } + 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<Self, BufReadError> { - Readable::read_int(buf) + Ok(buf.read_i32::<BE>()?) } } 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<Self, BufReadError> { - 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<Self, BufReadError> { - 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<T: McBufReadable + Send> McBufReadable for Vec<T> { default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<T: McBufReadable + Send> McBufReadable for Vec<T> { impl<K: McBufReadable + Send + Eq + Hash, V: McBufReadable + Send> McBufReadable for HashMap<K, V> { default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarRe for HashMap<K, V> { default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarRe impl McBufReadable for Vec<u8> { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<Self, BufReadError> { - buf.read_utf() + read_utf_with_len(buf, MAX_STRING_LENGTH.into()) } } impl McBufReadable for u32 { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<Self, BufReadError> { - 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<Self, BufReadError> { - 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<Self, BufReadError> { - buf.read_short() + Ok(buf.read_i16::<BE>()?) } } impl McBufVarReadable for u16 { fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - buf.read_varint().map(|i| i as u16) + Ok(i32::var_read_from(buf)? as u16) } } impl<T: McBufVarReadable> McBufVarReadable for Vec<T> { fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<T: McBufVarReadable> McBufVarReadable for Vec<T> { impl McBufReadable for i64 { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - buf.read_long() + Ok(buf.read_i64::<BE>()?) } } @@ -363,37 +248,37 @@ impl McBufReadable for u64 { impl McBufReadable for bool { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - buf.read_boolean() + Ok(u8::read_from(buf)? != 0) } } impl McBufReadable for u8 { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - buf.read_byte() + Ok(buf.read_u8()?) } } impl McBufReadable for i8 { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<Self, BufReadError> { - buf.read_float() + Ok(buf.read_f32::<BE>()?) } } impl McBufReadable for f64 { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - buf.read_double() + Ok(buf.read_f64::<BE>()?) } } impl<T: McBufReadable> McBufReadable for Option<T> { default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - 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<T: McBufReadable> McBufReadable for Option<T> { impl<T: McBufVarReadable> McBufVarReadable for Option<T> { default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { - let present = buf.read_boolean()?; + let present = bool::read_from(buf)?; Ok(if present { Some(T::var_read_from(buf)?) } else { diff --git a/azalea-buf/src/serializable_uuid.rs b/azalea-buf/src/serializable_uuid.rs index be93c5fd..66cdda73 100644 --- a/azalea-buf/src/serializable_uuid.rs +++ b/azalea-buf/src/serializable_uuid.rs @@ -1,4 +1,4 @@ -use crate::{read::BufReadError, McBufReadable, McBufWritable, Readable}; +use crate::{read::BufReadError, McBufReadable, McBufWritable}; use std::io::{Read, Write}; use uuid::Uuid; @@ -35,10 +35,10 @@ impl SerializableUuid for Uuid { impl McBufReadable for Uuid { fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { Ok(Uuid::from_int_array([ - Readable::read_int(buf)? as u32, - Readable::read_int(buf)? as u32, - Readable::read_int(buf)? as u32, - Readable::read_int(buf)? as u32, + u32::read_from(buf)?, + u32::read_from(buf)?, + u32::read_from(buf)?, + u32::read_from(buf)?, ])) } } @@ -54,7 +54,6 @@ impl McBufWritable for Uuid { } } -// TODO: add a test for Uuid in McBuf #[cfg(test)] mod tests { use super::*; diff --git a/azalea-buf/src/write.rs b/azalea-buf/src/write.rs index 15fa9680..0bbed25b 100644 --- a/azalea-buf/src/write.rs +++ b/azalea-buf/src/write.rs @@ -2,115 +2,22 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH}; use byteorder::{BigEndian, WriteBytesExt}; use std::{collections::HashMap, io::Write}; -// TODO: get rid of Writable and use McBufWritable everywhere - -pub trait Writable: Write { - fn write_list<F, T>(&mut self, list: &[T], writer: F) -> Result<(), std::io::Error> - where - F: FnOnce(&mut Self, &T) -> Result<(), std::io::Error> + Copy, - { - self.write_varint(list.len() as i32)?; - for item in list { - writer(self, item)?; - } - Ok(()) - } - - fn write_int_id_list(&mut self, list: &[i32]) -> Result<(), std::io::Error> { - self.write_list(list, |buf, n| buf.write_varint(*n)) - } - - fn write_map<KF, VF, KT, VT>( - &mut self, - map: Vec<(KT, VT)>, - key_writer: KF, - value_writer: VF, - ) -> Result<(), std::io::Error> - where - KF: Fn(&mut Self, KT) -> Result<(), std::io::Error> + Copy, - VF: Fn(&mut Self, VT) -> Result<(), std::io::Error> + Copy, - { - self.write_varint(map.len() as i32)?; - for (key, value) in map { - key_writer(self, key)?; - value_writer(self, value)?; - } - Ok(()) - } - - fn write_byte(&mut self, n: u8) -> Result<(), std::io::Error> { - WriteBytesExt::write_u8(self, n) - } - - fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> { - self.write_all(bytes)?; - Ok(()) - } - - fn write_varint(&mut self, mut value: i32) -> Result<(), std::io::Error> { - let mut buffer = [0]; - if value == 0 { - self.write_all(&buffer).unwrap(); - } - while value != 0 { - buffer[0] = (value & 0b0111_1111) as u8; - value = (value >> 7) & (i32::max_value() >> 6); - if value != 0 { - buffer[0] |= 0b1000_0000; - } - self.write_all(&buffer)?; - } - Ok(()) - } - - fn write_utf_with_len(&mut self, string: &str, len: usize) -> Result<(), std::io::Error> { - if string.len() > len { - panic!( - "String too big (was {} bytes encoded, max {})", - string.len(), - len - ); - } - self.write_varint(string.len() as i32)?; - self.write_bytes(string.as_bytes()) - } - - fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error> { - self.write_utf_with_len(string, MAX_STRING_LENGTH.into()) - } - - fn write_short(&mut self, n: i16) -> Result<(), std::io::Error> { - WriteBytesExt::write_i16::<BigEndian>(self, n) - } - - fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> { - self.write_varint(bytes.len() as i32)?; - self.write_bytes(bytes) - } - - fn write_int(&mut self, n: i32) -> Result<(), std::io::Error> { - WriteBytesExt::write_i32::<BigEndian>(self, n) - } - - fn write_boolean(&mut self, b: bool) -> Result<(), std::io::Error> { - self.write_byte(if b { 1 } else { 0 }) - } - - fn write_long(&mut self, n: i64) -> Result<(), std::io::Error> { - WriteBytesExt::write_i64::<BigEndian>(self, n) - } - - fn write_float(&mut self, n: f32) -> Result<(), std::io::Error> { - WriteBytesExt::write_f32::<BigEndian>(self, n) - } - - fn write_double(&mut self, n: f64) -> Result<(), std::io::Error> { - WriteBytesExt::write_f64::<BigEndian>(self, n) - } +fn write_utf_with_len( + buf: &mut impl Write, + string: &str, + len: usize, +) -> Result<(), std::io::Error> { + if string.len() > len { + panic!( + "String too big (was {} bytes encoded, max {})", + string.len(), + len + ); + } + string.as_bytes().to_vec().write_into(buf)?; + Ok(()) } -impl<W: Write + ?Sized> Writable for W {} - pub trait McBufWritable { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error>; } @@ -121,25 +28,48 @@ pub trait McBufVarWritable { impl McBufWritable for i32 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - Writable::write_int(buf, *self) + WriteBytesExt::write_i32::<BigEndian>(buf, *self) } } impl McBufVarWritable for i32 { fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_varint(*self) + let mut buffer = [0]; + let mut value = *self; + if value == 0 { + buf.write_all(&buffer).unwrap(); + } + while value != 0 { + buffer[0] = (value & 0b0111_1111) as u8; + value = (value >> 7) & (i32::max_value() >> 6); + if value != 0 { + buffer[0] |= 0b1000_0000; + } + buf.write_all(&buffer)?; + } + Ok(()) } } impl McBufWritable for UnsizedByteArray { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_bytes(self) + buf.write_all(self) } } impl<T: McBufWritable> McBufWritable for Vec<T> { default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_list(self, |buf, i| T::write_into(i, buf)) + self[..].write_into(buf) + } +} + +impl<T: McBufWritable> McBufWritable for [T] { + default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { + (self.len() as u32).var_write_into(buf)?; + for item in self { + T::write_into(item, buf)?; + } + Ok(()) } } @@ -169,13 +99,14 @@ impl<K: McBufWritable, V: McBufVarWritable> McBufVarWritable for HashMap<K, V> { impl McBufWritable for Vec<u8> { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_byte_array(self) + (self.len() as u32).var_write_into(buf)?; + buf.write_all(self) } } impl McBufWritable for String { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_utf(self) + write_utf_with_len(buf, self, MAX_STRING_LENGTH.into()) } } @@ -239,19 +170,19 @@ impl<T: McBufVarWritable> McBufVarWritable for Vec<T> { impl McBufWritable for u8 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_byte(*self) + WriteBytesExt::write_u8(buf, *self) } } impl McBufWritable for i16 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - Writable::write_short(buf, *self) + WriteBytesExt::write_i16::<BigEndian>(buf, *self) } } impl McBufWritable for i64 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - Writable::write_long(buf, *self) + WriteBytesExt::write_i64::<BigEndian>(buf, *self) } } @@ -263,35 +194,36 @@ impl McBufWritable for u64 { impl McBufWritable for bool { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_boolean(*self) + let byte: u8 = if *self { 1 } else { 0 }; + byte.write_into(buf) } } impl McBufWritable for i8 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_byte(*self as u8) + (*self as u8).write_into(buf) } } impl McBufWritable for f32 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_float(*self) + WriteBytesExt::write_f32::<BigEndian>(buf, *self) } } impl McBufWritable for f64 { fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { - buf.write_double(*self) + WriteBytesExt::write_f64::<BigEndian>(buf, *self) } } impl<T: McBufWritable> McBufWritable for Option<T> { default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { if let Some(s) = self { - buf.write_boolean(true)?; + true.write_into(buf)?; s.write_into(buf)?; } else { - buf.write_boolean(false)?; + false.write_into(buf)?; }; Ok(()) } @@ -300,10 +232,10 @@ impl<T: McBufWritable> McBufWritable for Option<T> { impl<T: McBufVarWritable> McBufVarWritable for Option<T> { default fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> { if let Some(s) = self { - buf.write_boolean(true)?; + true.write_into(buf)?; s.var_write_into(buf)?; } else { - buf.write_boolean(false)?; + false.write_into(buf)?; }; Ok(()) } |
