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/src | |
| parent | 32458d743f757da3193717fe5554f490703640c0 (diff) | |
| download | azalea-drasl-cfb190d00c70f1b09789e23f89a3c67840e0fd87.tar.xz | |
get rid of Readable & Writable (#21)
Diffstat (limited to 'azalea-buf/src')
| -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 |
4 files changed, 167 insertions, 378 deletions
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(()) } |
